Swift 中的不可变/可变集合

Immutable/Mutable Collections in Swift

提问人:Pranav Jaiswal 提问时间:6/7/2014 最后编辑:Pranav Jaiswal 更新时间:5/12/2021 访问量:92227

问:

我指的是 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的 目标-C 迅速 不变性 可变

评论


答:

5赞 iPatel 6/7/2014 #1

只需声明您的(任何)对象或变量

'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

阅读“The Swift Programming Language”。

评论

0赞 macshome 6/30/2014
好吧,在数组的情况下,这不能按预期工作。stackoverflow.com/a/24319712/623710
6赞 ColinE 6/7/2014 #2

Swift 中只有一种类型。可变性取决于你如何构造它:ArrayDictionary

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

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

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

评论

1赞 russbishop 6/24/2014
仅供参考:在即将到来的测试版中,数组行为正在发生变化;我想每个人都在谈论那个
0赞 Analog File 6/26/2014
@xenadu来源?该测试版的预计到达时间?
0赞 russbishop 6/27/2014
对不起,没有来源。它来自与编译器团队成员之一的讨论。他还表示,Beta 2 基本上只是几个已经检查过的错误修复,与 WWDC 后的反馈没有任何关系。
120赞 nicael #3

阵 列

创建不可变数组

第一种方式:

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"

有关 Apple Developer 的更多信息

评论

12赞 Sulthan 6/7/2014
“固定长度”数组会更精确。它不是一成不变的。
1赞 Bryan Chen 6/7/2014
immutable 是真正的不可变(与 Array 相反)Dictionary
0赞 nicael 6/7/2014
@BryanChen 是的,我忘了删除.var
2赞 Matt Gibson 6/7/2014
是的。有关此问题中数组的不变性及其答案的更多信息。
0赞 dopcn 9/12/2014
array += "Forth"在 Xcode 6 GM 中没有长时间的工作,将其更改为 或array += ["Forth"]array.append("Forth")
36赞 Abhi Beckert 6/23/2014 #4

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

有数组类和字典类,但应该注意的是,这些是“值”类型,而 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"]

您可以使用方法参数来实现 的行为:NSMutableArrayinout

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

func addToArray(inout myArray: [String]) {
  myArray.append("d")
}

addToArray(&myArray)

myArray // ["a", "b", "c", "d"]

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

评论

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

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

var arr1 : Array = []

arr1.bridgeToObjectiveC().count

它的工作原理相同。let

0赞 Balthazar 8/9/2015 #6

来自 Apple 自己的文档:

集合的可变性

如果创建数组、集合或字典并将其分配给 变量,则创建的集合将是可变的。这意味着 您可以在创建集合后更改(或更改)集合 添加、删除或更改集合中的项。相反,如果 将数组、集合或字典分配给常量,该常量 集合是不可变的,其大小和内容无法更改。

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

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

0赞 yoAlex5 7/16/2020 #7

Swift 可变/不可变集合

[不可修改和不可变]

Swift 的数组可以静音

[let vs var, 值 vs 引用类型]

不可变集合[关于] - 是无法更改的集合结构。这意味着创建后无法添加、删除、修改

let + struct(如 、 、 )更适合于不可变ArraySetDictionary

有些类(例如)提供更改内部状态的接口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