Swift中的不可变/可变集合


88

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

我希望在Objective-C中看到以下Swift中的等效项

不变数组

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"];

Answers:


115

数组

创建不可变数组

第一种方式:

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 2014年

1
不可变Dictionary是真正不可变的(与Array相反)
Bryan Chen

@BryanChen哦..谢谢!
nicael 2014年

@BryanChen是,我忘了删除var
nicael 2014年

2
对。有关此问题及其答案中数组的不变性的更多信息。
Matt Gibson 2014年

31

SwiftNSArray在Objective-C中没有替代品或其他集合类。

有数组和字典类,但应注意,与“对象”类型的NSArray和NSDictionary相比,它们是“值”类型。

差异是细微的,但对于避免边缘案例错误而言可能非常重要。

快速创建带有以下内容的“不可变”数组:

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"]

您可以NSMutableArray使用inoutmethod参数来实现的行为:

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 2015年

另外,正如我在回答中提到的那样,将值作为变量传递与可变性/不变性相关,因为您唯一关心的是将数组传递给其他代码(可能会对其进行修改)。
Abhi Beckert

但是,如果您将数组作为属性访问,则仍然可以从另一个对象对其进行修改。不变数组的好处之一是,您可以安全地将其传递给另一个对象,而不必担心另一个对象是否会修改原始对象。当对象作为值传递时,这种担心不再存在。因此,不同的语义需要不同的编码实践。编辑:我现在看到你已经改写了这个帖子,所以我们同意。我同意区别对于了解wrt很重要。使用可变集合。
Balthazar 2015年

6

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

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

即,如果您为变量创建分配,则该变量是可变的,而如果您为常量创建分配,则该变量是可变的。

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


1
仅供参考:阵列性能在即将发布的Beta版中正在发生变化;我想每个人都在谈论那个
russbishop 2014年

@xenadu来源?该版本的预计到达时间是多少?
模拟文件

抱歉,没有消息来源。它来自与一位编译器团队成员的讨论。他还说,Beta 2基本上只是几个已经检查过的错误修复程序,与WWDC后的反馈没有任何关系。
russbishop 2014年

5

只需使用以下命令声明您的(任何)对象或变量

'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

阅读“ Swift编程语言”。


好吧,在数组的情况下,它不能按预期工作。stackoverflow.com/a/24319712/623710
macshome 2014年

3

如果要Array像使用一样使用(Swift)NSArray,则可以使用简单的桥接功能。例:

var arr1 : Array = []

arr1.bridgeToObjectiveC().count

的工作原理相同let


0

来自苹果自己的文档:

集合的可变性

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

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

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


0

[不可更改且不可更改]

斯威夫特的数组可以静音

[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数组

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.