当值可能不存在(may be absent)的时候使用Optionals。
optional是说:There is a value, and it equals x.(我个人理解为:存在一个值,这个x就是所得到的值)
或者 There isn't a value at all.(根本不存在值)
NOTE
在C或者OC中不存在Optionals这个概念。在OC中最最近这个概念意思的是:在函数调用时,返回对象或者返回nil,这个nil意味着
有效对象的absence value.然后,这仅对对象起作用,对结构体、基本C类型或者枚举值类型不起作用,对于这些类型,OC中通过
返回NSNotFound这个特殊的值来表明absence value,通过这个值,函数调用者就可以检测处理。在Swift中,optionals可以是任何
类型,不需要特殊的常量表示。
看下面的例子:
// 这个字符串是完全由数字组成的 let possibleNumber = "123" // 这里调用toInt()方法时,转换可能会失败,所以返回的是Optional类型,也就是Int?类型, // 相当于Optional<Int>,返回值是说:要么有整型值,要么根本就没有值 // 因为这里possibleNumber完全是由数字组成的字符串,所以转换成功,因此得到整型值123 let convertedNumber = possibleNumber.toInt() // 这个字符串不是由数字组成的 let originalString = "hello, world" // 这里调用toInt()方法时,转换可能会失败,所以返回的是Optional类型,也就是Int?类型, // 因为这里的originalString不是由数字组成的,所以转换失败,返回值就是没有值 let resultNumber = originalString.toInt()
If 语句与强制拆包
可以使用if语句来检测optional是否包含值,如果包含值,就表示true,如果根本没有值,就表示false.
当我们确定optional包含值,可以使用!来访问,这个!放在这个optional名字后面。这个!表明:我知道这个
optional一定有值,请使用它。这就是所谓的:可选值的强制拆包(forced upwrapping of the optional's value)
看下面的例子:
// convertedNumber is an optional value // 如果convertedNumber存在值,那么表达式就是true if convertedNumber { // 如果能够进到这里,表示convertedNumber一定有值,那么我们就可以强制拆包 // 强制拆包就是在optional value后面添加一个!,也就是convertedNumber! // 但这也是需要注意的地方,使用强制拆包一定要确保这个可选值有值,否则 // 强制拆包会崩溃 println("\(possibleNumber) has an integer value of \(convertedNumber!)") } else { println("\(possibleNumber) could not be converted to an integer") }
NOTE
尝试使用!来访问不存在值的optional value 会触发运行时错误。当我们使用!来强制拆包(force-unwrap)的时候,
一定要确保这个optional value一定包含一个非nil 值。
可选绑定(optional binding)
我们可以使用optional binding来判断这个optional 是否包含一个值,确保值是可用的,并作为临时常量或者变量的值。
Optional binding可以使用if 和 while 语句中,用来检测optional是否包含值,并取出其中的值给常量或者变量。optional
binding的写法是:
if let constantName = someOptional { statements }
let possibleNumber = "123" if let actualNumber = possibleNumber.toInt() { println("\(possibleNumber) has an integer value of \(actualNumber)") } else { println("\(possibleNumber) could cant be converted to an integer") }
上面的例子中,我们只是单纯地打印actualNumber,所以用了let,如果我们需要另外操作,可以用var声明为变量,而不是常量。
可选值变量可以设置为nil,表示没有值
如下:
// 这个optional是Int?类型,初始值为404 var serverResponseCode: Int? = 404 // 把serverResponseCode设置为nil后,serverResponseCode现在不再有值,也就是Optional.None serverResponseCode = nil
NOTE
非optional类型常量和变量是不能设置为nil的,这与OC用的nil不同。
如果在代码中不确定这个变量或者常量是否有值,那么就声明为optional。
如果在定义Optional常量或者变量时,没有给定初始值,那么会自动设置为nil,表示Optional.None,即没有值。
如:
// surveyAnswer的值就是nil var surveyAnswer: String?
NOTE
SWIFT中的nil不同与OC中的nil,在OC中,nil表示不存在的对象。在Swit中,nil不是指针,只是表示某种类型的值不存在,
optional可以设置任何类型值为nil,不仅仅是对象类型。
隐式拆包可选值(Implicitly Unwrapped Optionals)
有时候,我们可以确定一旦变量或者常量被创建并初始化后,一直都会有值,那么可以就可以使用隐式拆包方式获取值。
在声明变量时,不是使用?来声明可选值,而是使用!来声明。
如:
let possibleString: String? = "An optional string." // 这是强制拆包 println(possibleString!) let assumedString: String! = "An implicitly unwrapped optional string." // 不需要添加!来拆包 println(assumedString)
NOTE
如果尝试访问的隐式拆包可选值不包含值,会触发运行时错误。
我们依然可以你正常的optional一样,使用if或者while 判断隐式拆包可选值是否包含值,如果包含值,会返回true,否则返回false
如:
if assumedString { println(assumedString) }
如果还可以像正常的optional一样使用optional binding来使用隐式拆包可选值。
如:
if let definiteString = assumedString { println(definiteString) }
NOTE
隐式拆包可选值不能出现不包含值的情况,否则会崩溃。所以如果不确定运行时值会不会出现nil,那么使用普通的optional会更好。