Swift提供了两种集合类型来存储集合的值:数组和字典。数组用来存储相同类型有序列表的值。字典用来存储相同类型无序集合的值,可以通过特殊标识符(key值)来引用和查找里面的元素。
Swift中的数组和字典通常清楚自己可以存储的值和键的类型。这意味着你无法向数组和集合中擦入错误的类型,这也意味着你可以放心的从数组和字典中检索值的类型(肯定不会出错)。Swift使用显式类型的集合以确保你的代码通常清楚值的类型且在你开发过程中很容易的捕捉到任何类型错误。
注意
在后台,Swift的数组和集合用泛型集合来实现,如果想了解更多的泛型集合的知识请看Generics。
如果你创建了任何数组或字典并把它赋给了变量,被创造的集合是可变的,这意味着在创造集合以后可以通过添加、删除、修改集合里的元素来改变集合。但是如果你把集合赋给了常量,那就意味着这个集合是不能被改变的。
注释
当一个集合在任何情况下都不需要改变的话,那么你可以创建一个不可变的集合,这样Swift的编译器会去优化使用你所创建的集合
一个数组顺序地存储相同类型的多个值,数组中的元素可以有重复值。Swift的数组明确规定了你可以存储的值的类型,他们不同于OC中NSArray和NAMutableArray类那样可以存储任意种类的对象且不提供他们返回的原生对象的任何信息。在Swift中,数组中只能存储特殊类型的值这种要求总是让代码更清晰,你也可以通过注释或者类型引用达到这种效果,但是没必要拥有一个class类型。如果你创建了一个Int的数组,你不能擦入其他类型的值到该数组,只能放入Int类型的值进去。Swift的数组是类型安全的,它通常知道数组应该包含什么类型的值。
Swift中的数组类型的全称为Array
你可以用一个数组常量来初始化一个数组,这是一种快速的方式将一个或多个值作为一个数组集合。一个数组常量通常包含一系列的值,以逗号分开,首尾以一对方括号包裹。
下面的例子中创建一个名叫shoppingList
的数组,用来存储String类型的值:
var shoppingList: [String] = ["Eggs", "Milk"]
// shoppingList has been initialized with two initial items
字典就是一个容器,容器里可以存放相同类型的多个值,每一个字都有一个唯一的key键用来唯一标识字典里的元素。不同于数组中的元素,字典里的元素没有特殊的顺序,如果你想去查看字典里的值你需要通过其标识符来访问。在真实世界里的字典也是通过以某个字母为关键字来查找的。
注意
字典是专门存储键值对类型的,它们不同于OC中的NSDictionary和NSMutableDictionary类。这两个类可以使用任何类型的对象作为字典的键或值
但是不提供任何关于原生对象的信息。在Swift中,字典中的键值对可以保存的类型通常是很清晰的,也可以通过注解和引用。
与数组类似,字典也有缩写写法,字典的全称为Dictionary
你可以用字典常量来初始化一个字典对象,字典常量定义的语法类似于数组常量,看来也很容易理解。字典常量是一中创建拥有一个或多个键值对字典集合的快捷方式。
一个键值对就是将一个键值和一个value值组合在一起。在字典常量中,键值和value值中间用冒号分开,而每一个键值对用分号分开,然后整个字典常量的前后用一对方括号包裹。
下面的例子为创建一个保存国际机场的字典。键值为机场的国际码,value值为机场的名称:
var airports: [String: String] = ["TYO": "Tokyo", "DUB": "Dublin"]//目前这种方式已经不对了。
var airports: Dictionary<String,String> = ["TYO": "Tokyo", "DUB": "Dublin"]
airports字典为[String,String]类型的,意味着它的key类型为String,value类型也为String.
注意 上面的字典是一个变量而不是一个常量,因为会有更多的机场信息加到上面的字典中。
上面的airports字典是用包含2个键值对的字典常量初始化的字典变量。第一个键值对的key值为TYO,value值为Tokyo.第二个键值对的key值为DUB,value值为Dublin.
(以下为废话)例子中的字典包含2个String:String键值对,符合airports变量的类型定义(key值为String类型,value值为String类型),所以字典常量可以分配2个字典元素来初始化airports字典。
与数组一样,如果你用字典初始化文字的键和值类型一致的,您不必编写字典的类型。机场的初始化可以用下面的简写形式:
var airports = ["TYO": "Tokyo", "DUB": "Dublin"]
你可以通过字典的方法和属性或者下标的方式来访问和修改字典中的元素。与数组类似,你可以调用它的只读属性count来获得字典中的元素个数。
println("The dictionary of airports contains \(airports.count) items.")
// prints "The dictionary of airports contains 2 items."
你可以用下标的方式添加一个新的元素到字典中,用一个正确类型的key值作为下标,然后分配一个正确类型的value值。
airports["LHR"] = "London"
// the airports dictionary now contains 3 items
你也可以用下标的方式来修改某个元素的值。
airports["LHR"] = "London Heathrow"
// the value for "LHR" has been changed to "London Heathrow"
作为用来替代下标的方式,使用字典的updateValue(forKey:)方法来给特定key值元素设置和更新其中的值。类似上例中的下标,如果下标值不存在,会添加一个值,如果下标值存在那就变为修改值。然后与下标不同的是,如果是更新的话会返回更新前的 旧值,这可以让你判断是否成功更新了一个值。
updateValue(forKey:)方法返回字典值类型的一个可选值。例如,一个字典存储的是String类型的值,那么方法返回的值就为String?或“Optional String”。这个可选值包含了成功更改后的旧值,也包含添加新的键值后返回的nil值。
if let oldValue = airports.updateValue("Dublin International", forKey: "DUB") {
println("The old value for DUB was \(oldValue).")
}
// prints "The old value for DUB was Dublin."
你可以用下标法去检索字典中某个key值对应的value值。因为它可能请求的key值没有对应的value值,所有返回的值也是值类型的可选值。如果字典包含你所请求的key值所对应的value值,那么返回的可选值中就包含了对应的value值,否则就返回nil值。
if let airportName = airports["DUB"] {
println("The name of the airport is \(airportName).")
} else {
println("That airport is not in the airports dictionary.")
}
// prints "The name of the airport is Dublin International."
你可以通过下标值来给key值对应的值赋上nil来从字典中删除这个键值对。
airports["APL"] = "Apple International"
// "Apple International" is not the real airport for APL, so delete it
airports["APL"] = nil
// APL has now been removed from the dictionary
或者,调用字典的removeValueKey方法也可以删除某一个元素,这个方法如果删除的键值对存在,则会返回这个被删除的值,如果不存在那么就返回nil值。
if let removedValue = airports.removeValueForKey("DUB") {
println("The removed airport's name is \(removedValue).")
} else {
println("The airports dictionary does not contain a value for DUB.")
}
// prints "The removed airport's name is Dublin International."
可以使用for-in循环来遍历字典。字典中的每个元素会返回一个(key,value)的元组,然后你可以将这个元组分解,然后将其存储在迭代模块里的临时变量或者常量中。
for (airportCode, airportName) in airports {
println("\(airportCode): \(airportName)")
}
// TYO: Tokyo
// LHR: London Heathrow
你也可以单独迭代字典集合中的key值或value值,通过字典属性keys(只包含key值集合)或values(只包含values值的集合)。
for airportCode in airports.keys {
println("Airport code: \(airportCode)")
}
// Airport code: TYO
// Airport code: LHR
for airportName in airports.values {
println("Airport name: \(airportName)")
}
// Airport name: Tokyo
// Airport name: London Heathrow
你也可以调用api用字典的keys或values属性得到的结果初始化一个Array对象:
let airportCodes = [String](airports.keys)
// airportCodes is ["TYO", "LHR"]
let airportNames = [String](airports.values)
// airportNames is ["Tokyo", "London Heathrow"]
注意
Swift的字典类型是一个无序的集合,遍历values,keys,键值对的顺序都是随机的。
你也可以创建一个空字典,但是要有确切的类型。
var namesOfIntegers = [Int: String]()
// namesOfIntegers is an empty [Int: String] dictionary
上面的例子创建一个空字典namesOfIntegers,用来存储可读的整型值名称,key值类型为Int,value值类型为String.
如果上下文已经提供了类型信息,可以使用一个空的字典文本创建一个空的字典,写成[:](一对方括号中加一个冒号):
namesOfIntegers[16] = "sixteen"
// namesOfIntegers now contains 1 key-value pair
namesOfIntegers = [:]
// namesOfIntegers is once again an empty dictionary of type [Int: String]
字典中的key值类型必须是hashable的类型,因为类型必须提供一种方式去计算自身的哈希值。一个哈希值是一个Int类型的值,且适用于所有的对象匹配。例如a=b可以写成a.hashcode=b.hashcode。
Swift中的所有基础类型(String,Int,Double和Bool)默认都有哈希值,而且这些类型都可以用于字典的key值类型。无相关值(Enumerations一文中定义的)的枚举成员值也是可以被hashable的。
意思是只要对象含有hasdcode这个属性都可以作为字典的key值使用。
注意
你可以在字典的键类型中使用自定义的类型,但是必须符合Swift标准库中的hashable协议。协议规定你自定义的类型必须提供一个可获取的Int类型的值叫hashValue
且必须实现等于的操作(is equal或者==).类型的hasValue属性返回的值有可能因为相同程序但是执行方式不同而不同,也有可能因为不同程序而不同。如果想了解更多信息
参考Protocols
(完!)
有人已经翻译完了,我就到此结束了。
swift教程中文版