1 - Optionals
Optionals的设计初衷,应该是体会到了各种dreaded null pointer。
在playground中输入以下代码:
var str
println(str)
将会得到报错:
Type annotation missing in pattern
这表明编译器不知道str的类型
于是将代码改写成:
var str: String
println(str)
又得到报错:
Variable 'str' used before being initialized
Swift是不允许你在compile time使用一个未经初始化的变量的。
如果真的需要一个值为nil的对象,该怎么办呢?
如果将代码更改成:
var str: String = nil
println(str)
会得到报错:
Type 'string' does not conform to protocol 'NilLiteralConvertible'
既然将变量申明成String类型,那它就必须是个string,nil的类型并不是String,so出现错误。
但如果真的需要使用一个nil值,那就可以使用optional。Optionals are a way of wrapping up the concept of "has a value(有值)" or "may have a value(可能有值)" into a language-wide feature.
(1)Declaring optionals
var str: String?
这里类型后添加的question mark,就表明出这个字符串是optional的。这里,可以把optional想象成一种独立的类型,所以变量str可以存入nil或者是一个String类型的实例。当把str初始化为nil时,其实就是没有显式地分配给str一个String实例。
如果将代码改成:
var str: String? = "Hi Loi!"
println(str)
可以在playground的侧边栏看到{Some “Hi Loi!”},包装wrapping就长这个样,字符串被包装,花括号{}和“Some”表明这是一个optional类型。
如果加一句代码:
var str: String? = "Hi Loi!"
println(str)
str = str.uppercaseString
就会得到报错:
‘String?’ does not have a member named 'uppercaseString'
optional类型实际上是没有uppercaseString这个method的。
改写代码:
var str: String? = "Hi Loi!"
println(str)
if let unwrappedStr = str {
println("Unwrapped! \(unwrappedStr.lowercaseString) ")
}
通过这个if statement,str被拆包了,并且赋了一个新的常量unwrappedStr,在if语句中,如果现在str包装的是一个字符串的实例,那unwrappedStr就变成一个String类型的变量,if语句的条件就可以pass,println语句就可以执行。
如果把代码改写成:
var str: String?
println(str)
if let unwrappedStr = str {
println("Unwrapped! \(unwrappedStr.lowercaseString) ")
} else {
println("nil")
}
这时候optional str就被包装成了nil,if语句条件就无法pass了,else后面的语句就执行了。
(2)Forced unwrapping
如果能够确定optional有值,可以使用强制拆包。
但如果此时optional实际上是nil就会产生run time error,这样会造成app crash
改写代码:
var str: String?
println(str)
println("Force unwrapped \(str!.lowercaseString)") //Fetal Error
(3)Implicit unwrapping
var str: String! = "Hi Loi!"
(4)Optional chaining
Optional chaining is a concise way to work with optionals quickly without using if/let and a conditional block each time.
var isString: String? = "Hi loi"
let lowerCase = isString?.lowercaseString
在第一行声明一个optional的字符串isString,然后在第二行变量后的?就是optional chaining的开始。
在run time,先check一下optional的isString的内容是不是真的存在,如果isString里确实包含一个实例,那就执行表达式lowercaseString,如果isString是nil,那就返回nil。
2 - Collection
在Swift中,只有两种primitive collection类型:arrays和dictionaries
(1)Array
Arrays provide an ordered list of elements.
var array:[Int] = [1, 2, 3, 4, 5]
println(array[3])
array.append(6)
println(array)
array.extend(7...10)
(2)Dictionaries
Dictionaries provide a list of mappings between keys and values.
var dictionary = [1: "Dog", 2: "Cat"]
var dictionary2: [Int:String] = [1: "Yes", 2: "No"]
println(dictionary[2])
dictionary[3] = "Tiger"
println(dictionary)
dictionary[1] = nil
println(dictionary)
if let value = dictionary[1] {
println("\(value)")
} else {
println("No value")
}
(
3)References and copies
Dictionaries are copied when you assign them to new variables and constants, or when you pass them as parameters to functions.
var dictionaryA = [1: 1, 2: 4, 3: 9, 4: 16]
var dictionaryB = dictionaryA
println(dictionaryA)
println(dictionaryB)
dictionaryB[4] = nil
println(dictionaryA)
println(dictionaryB)
var arrayA = [1, 2, 3, 4, 5]
var arrayB = arrayA
println(arrayA)
println(arrayB)
//arrayB.removeAtIndex(0)
arrayB[0] = 10
println(arrayA)
println(arrayB)
let constantArray = [1, 2, 3, 4, 5]
constantArray.append(6)
constantArray.removeAtIndex(0)
报错:
1. immutable value of type '[Int]' only has mutating members named 'append'
2. immutable value of type '[Int]' only has mutating members named 'removeAtIndex'