【问题标题】:Immutable/Mutable Collections in SwiftSwift 中的不可变/可变集合
【发布时间】:2014-06-07 10:11:11
【问题描述】:

我指的是 Apple 的 Swift 编程指南,以了解在 Swift 语言中创建可变/不可变对象(数组、字典、集合、数据)。但我不明白如何在 Swift 中创建不可变集合。

我想在 Swift 中看到 Objective-C 中以下内容的等价物

不可变数组

NSArray *imArray = [[NSArray alloc]initWithObjects:@"First",@"Second",@"Third",nil];

可变数组

NSMutableArray *mArray = [[NSMutableArray alloc]initWithObjects:@"First",@"Second",@"Third",nil];
[mArray addObject:@"Fourth"];

不可变字典

NSDictionary *imDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:@"Value1", @"Key1", @"Value2", @"Key2", nil];

可变字典

NSMutableDictionary *mDictionary = [[NSMutableDictionary alloc]initWithObjectsAndKeys:@"Value1", @"Key1", @"Value2", @"Key2", nil];
[mDictionary setObject:@"Value3" forKey:@"Key3"];

【问题讨论】:

    标签: ios objective-c swift immutability mutable


    【解决方案1】:

    数组

    创建不可变数组

    第一种方式:

    let array = NSArray(array: ["First","Second","Third"])
    

    第二种方式:

    let array = ["First","Second","Third"]
    

    创建可变数组

    var array = ["First","Second","Third"]
    

    将对象附加到数组

    array.append("Forth")
    


    字典

    创建不可变字典

    let dictionary = ["Item 1": "description", "Item 2": "description"]
    

    创建可变字典

    var dictionary = ["Item 1": "description", "Item 2": "description"]
    

    将新配对添加到字典中

    dictionary["Item 3"] = "description"
    

    More information on Apple Developer

    【讨论】:

    • “固定长度”数组会更精确。它不是一成不变的。
    • 不可变 Dictionary 是真正不可变的(与 Array 相反)
    • @BryanChen 哦.. 谢谢!
    • @BryanChen 是的,我忘了删除var
    • 是的。在this question and its answers 中了解有关数组不可变性的更多信息。
    【解决方案2】:

    Swift 没有替代 NSArray 或 Objective-C 中的其他集合类。

    有数组和字典类,但应该注意的是,这些是“值”类型,而 NSArray 和 NSDictionary 是“对象”类型。

    差异很小,但对于避免极端情况错误非常重要。

    在 swift 中,您创建一个“不可变”数组:

    let hello = ["a", "b", "c"]
    

    还有一个“可变”数组:

    var hello = ["a", "b", "c"]
    

    可变数组可以像NSMutableArray一样修改:

    var myArray = ["a", "b", "c"]
    
    myArray.append("d") // ["a", "b", "c", "d"]
    

    但是您不能将可变数组传递给函数:

    var myArray = ["a", "b", "c"]
    
    func addToArray(myArray: [String]) {
      myArray.append("d") // compile error
    }
    

    但上面的代码确实适用于 NSMutableArray:

    var myArray = ["a", "b", "c"] as NSMutableArray
    
    func addToArray(myArray: NSMutableArray) {
      myArray.addObject("d")
    }
    
    addToArray(myArray)
    
    myArray // ["a", "b", "c", "d"]
    

    您可以通过使用inout 方法参数来实现NSMutableArray 的行为:

    var myArray = ["a", "b", "c"]
    
    func addToArray(inout myArray: [String]) {
      myArray.append("d")
    }
    
    addToArray(&myArray)
    
    myArray // ["a", "b", "c", "d"]
    

    2015-08-10 重写了这个答案,以反映当前的 Swift 行为。

    【讨论】:

    • 这显然已经改变了。常量数组现在是真正不可变的,而变量数组现在是真正可变的。它们作为 传递,因此它们将在分配给另一个变量或在函数之间传递时被复制。然而,这与可变性或不变性无关。
    • 正如我在回答中提到的,作为值传递与可变性/不变性有关,因为您唯一关心的是将数组传递给其他代码(可能会对其进行修改)。
    • 但是如果您将数组作为属性访问,您仍然可以从另一个对象对其进行修改。不可变数组的好处之一是您可以安全地将其传递给另一个对象,而不必担心另一个对象是否会修改原始数组。当对象作为值传递时,这个问题就不再存在了。因此,不同的语义需要不同的编码实践。编辑:我现在看到你已经改写了这篇文章,所以我们同意。我同意这些差异对于了解 wrt 很重要。可变集合的使用。
    【解决方案3】:

    在 Swift 中只有一个 Array 和一个 Dictionary 类型。可变性取决于您如何构造它:

    var mutableArray = [1,2,3]
    let immutableArray = [1,2,3]
    

    即如果你创建一个赋值给一个变量,它是可变的,而如果你创建一个赋值给常量,它不是。

    警告:不可变数组并非完全不可变!您仍然可以更改它们的内容,但不能更改它们的总长度!

    【讨论】:

    • 仅供参考:数组行为在即将到来的测试版中发生变化;我想每个人都在谈论那个
    • @xenadu 来源?那个测试版的预计到达时间?
    • 对不起,没有来源。它来自与编译器团队成员之一的讨论。他还说 Beta 2 基本上只是几个已经签入的错误修复,与 WWDC 后的反馈没有任何关系。
    【解决方案4】:

    只需用

    声明您的(任何)对象或变量
    'let' key word -> for "constan/Immutable" array, dictionary, variable, object..etc.
    

    'var' key word -> for "Mutable" array, dictionary, variable, object..etc. 
    

    了解更深入的信息

    “使用 let 制作常量,使用 var 制作变量。常量的值不需要在编译时就知道,但你必须给它赋值一次。这意味着您可以使用常量来命名您确定一次但在许多地方使用的值。”

    var myVariable = 42
    myVariable = 50
    let myConstant = 42
    

    Read “The Swift Programming Language.”

    【讨论】:

    【解决方案5】:

    如果您想像使用NSArray 一样使用Array (Swift),您可以使用一个简单的桥接函数。示例:

    var arr1 : Array = []
    
    arr1.bridgeToObjectiveC().count
    

    let 也一样。

    【讨论】:

      【解决方案6】:

      来自 Apple 自己的文档:

      集合的可变性

      如果您创建一个数组、集合或字典并将其分配给 变量,创建的集合将是可变的。这表示 您可以在创建集合后更改(或变异)集合 添加、删除或更改集合中的项目。相反,如果 您将数组、集合或字典分配给常量,即 集合是不可变的,它的大小和内容不能改变。

      https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-ID105

      不可变/可变集合的其他用途取决于您希望它们可变/不可变的原因。集合是 Swift 中的 value 类型,这意味着当它们被分配给另一个值或传递给另一个函数/方法时,它们的内容会被复制。因此,您无需担心接收方法函数是否会更改原始数组。因此,例如,如果您的类持有可变集合,则无需确保返回不可变集合。

      【讨论】:

        【解决方案7】:

        Swift 可变/不可变集合

        [Unmodifiable and Immutable]

        Swift 的数组可以静音

        [let vs var, Value vs Reference Type]

        不可变集合[About] - 是一个不能改变的集合结构。表示创建后不能添加、删除、修改

        let + struct(like Array, Set, Dictionary) 更适合不可变

        有些类(例如NSArray提供改变内部状态的接口

        但是

        class A {
            var value = "a"
        }
        
        func testMutability() {
            //given
            let a = A()
            
            let immutableArr1 = NSArray(array: [a])
            let immutableArr2 = [a]
            
            //when
            a.value = "aa"
            
            //then
            XCTAssertEqual("aa", (immutableArr1[0] as! A).value)
            XCTAssertEqual("aa", immutableArr2[0].value)
        }   
        

        宁愿是unmodifiable数组

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-01-07
          • 2012-01-19
          • 2011-03-11
          • 1970-01-01
          • 2012-02-12
          • 1970-01-01
          • 2013-08-30
          相关资源
          最近更新 更多