一、Optional类型的概念

Swift中为何要引入Optional的概念,官方文档中有介绍:

Swift also introduces optional types, which handle the absence of a value. Optionals say either “there is a value, and it equals x” or “there isn’t a value at all”. Using optionals is similar to using 

nil with pointers in Objective-C, but they work for any type, not just classes. Not only are optionals safer and more expressive than 

nil pointers in Objective-C, they’re at the heart of many of Swift’s most powerful features.


总结下来就是:可选类型用来表示“有一个值,它等于x或者根本没有值”。当我们遇到Optional类型时,就会明显知道这里的值可能为nil,我们必须谨慎处理。这样的做法要比Objective-C更加安全和表现力。说白了,可选类型的引入既安全写起来有便捷。

二、Optional类型的实现

var optionalInteger: Int?

var optionalInteger: Int!

其中?和!都是可选类型的语法糖。

三、Optional类型的本质

Optional其实是个枚举(enum)(严格来讲:应该是enum和泛型为基础的高阶抽象类型),分别是None和Some(T),如果可选类型为nil就会命中None的Case。

enum Optional<T> : NilLiteralConvertible, Reflectable {  
        case None  
        case Some(T)  

        //...
}

如果命中Some(T)的Case,就会得到一个“包装”后的值(a wrapped value),如果想要拿到真正的value,就需要“拆包”,否则你会得到的是Optional(value)。

四、Optional类型的运用(拆包)

1、可选绑定

此种情况如果包含就把值赋给一个临时常量或者变量。可选绑定可以用在if和while语句中来对可选类型的值进行判断并把值赋给一个常量或者变量。

基本写法:

if let constantName = someOptional {
    statements
}

示例:

var myString:String?
myString = "Hello, Swift!"
if let yourString = myString {
   print("你的字符串值为 - \(yourString)")
}else{
   print("你的字符串没有值")
}

2、强制解析

示例:

var myString:String?
myString = "Hello, world!"
if myString != nil {
   // 强制解析
   print( myString! )
}else{
   print("myString 值为 nil")
}

此时如果myString为nil,那么以上代码将会出现运行时错误。

五、Optional类型注意事项

1、使用!进行强制解包时,要确保变量值是非nil的

var str1:String?  // str1值可能是传过来的值或者从服务器获取的值
let msg = "Hi"
let txt = msg + str1!  // runtime error

swift present弹出窗口 swift optionset_可选绑定

所以,需要谨慎使用。

2、??运算符(空和运算符)

这是一个常见而且非常有用的操作符。我们在解包变量时,时常被提示提供一个default value。

swift present弹出窗口 swift optionset_swift present弹出窗口_02

它的作用如下:

(以下代码,摘录自https://www.jianshu.com/p/e304658fbfca?utm_source=oschina-app):

// 写法一:可选绑定(Optional Binding)
var username = ""
if let name = inputName {
    username = name
} else {
    username = "Guest"
}
// 写法二:三目运算符(ternary operator)
let username = inputName != nil ? inputName! : "Guest"

以上代码等同于:

let username = inputName ?? "Guest"

a??b的意思是:可选类型a先进行判空判断,如果a包含一个值,就进行解封,否则就返回默认值b。注意:表达式a必须是Optional类型,默认值b的类型须要和a存储值的类型保持一致。

注意:??有时也有可能表示多重Optional,例如:

var string: String? = "string"
var anotherString: String?? = string

我们可以很明白地知道 anotherString 是 Optinal<Optional<String>>

3、Optional Chaining可选链

Swift官网有介绍如下:

Optional chaining is a process for querying and calling properties, methods, and subscripts on an optional that might currently be nil. If the optional contains a value, the property, method, or subscript call succeeds; if the optional is nil, the property, method, or subscript call returns nil. Multiple queries can be chained together, and the entire chain fails gracefully if any link in the chain is nil.

大致意思:

可选链是查询和调用当前可能为零的可选链上的属性、方法和下标的过程。如果可选项包含值,则属性、方法或下标调用成功;如果可选值为nil,则属性、方法或下标调用将返回nil。多个查询可以链接在一起,如果链中的任何链接为零,则整个链都会正常失败。

示例如下:

class Person {
	var residence: Residence?
}
class Residence {
    var numberOfRooms = 1
}
let john = Person()
//如果写成强制解包,此段代码会有运行时报错
let roomCount = john.residence!.numberOfRooms
//正确写法
//john.residence = Residence()
if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}