Optional 作为 Swift 中最重要的语言特性之一,下面来解读下 Optional 的源码。
Optional 在 Swift 中是一个包含 none 和 some 两个 case 的 enum:
public enum Optional<Wrapped> : ExpressibleByNilLiteral {
/// 代码中使用 nil 来代替 none 的枚举
case none
/// The presence of a value, stored as `Wrapped`.
case some(Wrapped)
}
case none 在代码中用 nil 来代码,即 nil == .none,我们可以通过代码来验证一下:
print(nil == Optional.none) // true
如果存在一个值使用 some(Wrapped):
let num: Int? = 1
print(num) // Optional(1)
switch num {
case .some(let n):
print(n) // 1
case .none:
print("nim is nil")
}
在 Optional 中的 map 方法
@_inlineable
public func map<U>(
_ transform: (Wrapped) throws -> U
) rethrows -> U? {
switch self {
case .some(let y):
return .some(try transform(y))
case .none:
return .none
}
}
Optional 类型进行 map 方法里,如果值为 none 时, 直接返回 nil,如果为 some(Wrapped) 时,返回 some(transform(Wrapped)),可以通过以下代码来验证:
let num1: Int? = nil
print (num1.map { $0 * 2 }) // nil
let num2: Int? = 2
print (num2.map { $0 * 2 }) // Optional(4)
在 Optional 中的 flatMap 方法
@_inlineable
public func flatMap<U>(
_ transform: (Wrapped) throws -> U?
) rethrows -> U? {
switch self {
case .some(let y):
return try transform(y)
case .none:
return .none
}
}
Optional 中的 flatMap 方法,如果值为 nil 时,直接我返回 nil,如果不为 nil 时,some 进行解包并 transform。需要注意的是,transform 时是解包值,但 return 返回的还是 Optional
let num1: Int? = nil
print (num1.flatMap { $0 * 2 }) // nil
let num2: Int? = 2
num2.flatMap { print($0 * 2) } // 4
print (num2.flatMap { $0 * 2 }) // Optional(4)
关于更多 map 和 flatMap 内容,可以参看 Swift 源码解读 - Map.swift 一文
unsafelyUnwrapped
@_inlineable
public var unsafelyUnwrapped: Wrapped {
@inline(__always)
get {
if let x = self {
return x
}
_debugPreconditionFailure("unsafelyUnwrapped of nil optional")
}
}
unsafelyUnwrapped 和 强制解包符 ! 的功能是相似的,如果为 nil 时执行,则会报错:
let num1: Int? = 2
print(num1!) // 2
print(num1.unsafelyUnwrapped) // 2
let num2: Int? = nil
print(num2!) // Fatal error: Unexpectedly found nil while unwrapping an Optional value
print(num2.unsafelyUnwrapped) // Fatal error: unsafelyUnwrapped of nil optional
Optional.swift 文件里面还有一些 == 、 != 、?? 等方法的实现,以及和 OC 桥接的内容,这里就不一一讲解,有兴趣可以自己研究下。
扩展 - Optional 常用方法
- ! 强制解包符 // 如果为 nil 时, 运行时会出错
- if let x = x {}
- guard let x = x else { return } // 推荐用法
网友评论