可选类型、隐式可选类型
在Swift 中可选类型是一个枚举类型(Enum),里面有None和非None两种类型,nil对应于Optional.None;非nil对应于Optional.Some(Wrapped),通过Some(Wrapped) 包装原始值,这也是为什么在使用Optional的时候要拆包(从Enum中的Some取出原始值)的原因,同理在PlayGround中会把Optional值显示为类似{Some”Hello World”},以下是Enum Optional的定义1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible {
case None
case Some(Wrapped)
/// Construct a `nil` instance.
public init()
/// Construct a non-`nil` instance that stores `some`.
public init(_ some: Wrapped)
/// If `self == nil`, returns `nil`. Otherwise, returns `f(self!)`.
@rethrows public func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U?
/// Returns `nil` if `self` is nil, `f(self!)` otherwise.
@rethrows public func flatMap<U>(@noescape f: (Wrapped) throws -> U?) rethrows -> U?
/// Create an instance initialized with `nil`.
public init(nilLiteral: ())
}
语法“?”使用
1.申明Optional值变量
1 | var optionalName:String? = “Hello John”//定义一个可选变量optionalName并进行初始化 |
第一次输出和第二次输出的不同正好验证了上面的介绍,直接打印一个Optional变量,会打印出包装后的枚举值Some(Wrapped),如果要取得原始值必须进行拆包操作,即optionalName!拆包后打印出的值为原始值”Hello John”
如果打开第二行的注释,//optionalName = nil 相当于var optionalName:String,即不对optionalName进行初始化,第一次输出为nil,第二次输入的代码编译不过,因为这是一个可选变量,当变量为nil时,自动验证是否有可选的值,有则使用可选值,加上!访问符来访问optionalName变量,由于optionalName的值为nil,并没有包含一个实际值,所以抛出异常。可以用以下代码代替1
2
3
4
5
6
7
8
9
10
11
12//写法一
if (optionalName != nil) {
print(optionalName!)
}
//写法二
if let temp = optionalName {
print(temp)
}
//写法三
if var temp = optionalName {
print(temp)
}
2.用在对Optional值操作时,判断是否能响应后面的操作,且看示例
1 | var button:UIButton? |
语法”!”的使用
上面已经用到了!,主要是用来:
1.定义隐式可选变量
1 | var button:UIButton! = UIButton()//定义一个隐式可选变量button,一定为非nil,在使用的时候不用每次都用?号判断是否为nil |
2.拆包可选变量
可选类型变量,不能直接进行操作,否则会报错。因此要访问值就需要拆包。拆包有两种。
第一种:使用if let/var xxx =1
2
3
4var optionalName:String? = "Hello"
if let temp = optional {
//code
}
第二种:使用!号1
2var optionalName:String? = "Hello"
let hv = optionalName!.hashValue //这里的!表示这里的optionalName一定是非nil的,否则会报错
总结
在Swift中任何变量/常量的声明都必须带有初始值,否则就要声明为可选类型。
即var name:String 这样是编译不过的。必须改为带初始化的如:
1 | var name:String = “John" |
或者使用?或者!来约束,因此常常声明可选或隐式可选变量
1 | var name:String? //可选变量,在程序中不能确定该变量是否为nil的情况下使用 |
感悟:
可选类型是Swift推出的全新语言类型,任何变量声明的同时必须进行初始化,否则就必须使用可选,在使用可选变量的时候赋值和使用都不方便,于是Swift推出隐式可选变量,使得申明的时候不用赋初值,使用过程中也不需要每次拆包以及验证是否为nil,但是付出的代价就是牺牲一定的安全性。