swift中?和!的出现,归根结底的原因,我认为是swift在设计时引入的一个重要概念,就是所有的变量必须初始化,如果不初始化,就无法通过编译器的检查。这么做的好处就是从一开始就规避了因为变量未初始化导致的一些奇奇怪怪的bug。下面代码展示了在使用一个未初始化的变量时,编译器报出的错误。
var variable:Int
print(variable)
//Variable 'variable' used before being initialized
1.可选类型
swift默认要求所有变量必须初始化,但是开发过程中,或许会遇到一些对象的成员变量或者其他变量,并不会用到,也没有必要初始化。这时就用到了swift为我们提供的可选类型,就是表示程序员知道变量必须初始化,但是根据程序逻辑,程序员认为不是一定要初始化该变量。例如上面的例子,可以写成如下:
var variable:Int?
print(variable)
//nil
或者不用”?”用”Optional”关键字
var variable:Optional
print(variable)
//nil
声明为可选类型之后,编译就可以通过了,因为是程序员手动声明为可选类型,说明程序员已经了解了该变量可能并不会初始化,程序员可以对该变量负责。
下面说一下这个”nil”,可选类型不初始化的情况下,变量的值为nil,这个nil和Objective-C中的nil并不相同,从一些swift语言的学习书籍中找到了下面的说明:
- 在Objective-C中nil表示的是一个指向不存在对象的指针,而swift中表示空的关键字为”nil”,它没有其他含义。
- 可选类型的变量或者常量在有值的时候返回值,没有值的时候不会返回任何东西,包括false。
- nil不能用于非可选的变量或者常量,如果你的代码中可能会出现没有值的情况,请务必声明其为可选类型,如果你声明了一个可选变量或者常量没有初始化,程序会默认赋值为nil
1.1可选链,可选链就是将可选的调用链接在一起形成一个链,如果任何一个节点为空(nil),将导致整个可选链失效。见如下示例:
class Student {
var country:Country?
}
class Country {
var name:String = "China"
var capital:Capital?
}
class Capital{
var mayor:String = "Mayor Liu"
var name:String="Beijing"
}
var xiaoli = Student()
xiaoli.country = Country()
if let country = xiaoli.country?.capital?.name {
print("Xiaoli is from \(xiaoli.country?.capital?.name)")
} else {
print("不知道哪来的!!!")
}
2.隐式解析可选
隐式解析可选和可选类型相似,都是由程序员对变量的初始化负责。隐式解析可选的含义是确定变量或者常量一定有值。如下代码,使用!将变量variable声明为隐式解析可选,就相当于程序员在声明的时候告诉编译器,确定该变量一定会有值,这样就编译器就不会抛出变量未初始化的错误。虽然躲过了编译器的检查,但是程序真正运行时,由于变量variable未初始化,值为nil,所以程序会crash。
var variable:Int!
print(variable)
//fatal error: unexpectedly found nil while unwrapping an Optional value
2.1隐式解析可选的其他使用
有时候在编码的过程中由上下文的逻辑能清晰的确定变量有值,这时就可以选择使用隐式解析可选,如下示例:
class Student {
var country: Country?
}
class Country {
var name:String="China"
}
var xiaoli = Student()
xiaoli.country = Country()
var name = xiaoli.country!.name;
print(name)