Swift中Optional的map和flatMap
2016-07-12 本文已影响473人
liushuaikobe
用过Swift的读者想必对map
和flatMap
不陌生,它们定义在SequenceType
协议及其extension中,讲它们用法的文章一大堆,我就不拾人牙慧了。
但是不知读者是否知道,Swift中的Optional类型,也有map
和flatMap
方法。
首先看这样的场景:
let avatarURL: String? = "http://blog.liushuaiko.be/images/avatar.PNG"
不妨假设avatarURL
的来源以及是否有值我们不得而知,因此我们将其定义为一个Optional<String>
类型。在使用它时,我们需要做一系列的判断赋值:
if let _avatarURL = avatarURL {
if let url = NSURL(string: _avatarURL) {
print(url.absoluteString)
}
}
这样的场景通常在解析网络请求返回的JSON时很常见,不知不觉就出现了所谓的「大括号阶梯」。
我们可以用Optional类型中定义的map
和flatMap
来避免这种情况,先看下用了之后会变成什么样子:
avatarURL.flatMap {
return NSURL(string: $0)
}.map {
print($0.absoluteString)
}
打开Optional
的定义,map
和flatMap
一览无余,你应该顺便发现,Optional在Swift里是一个enum。
去掉@noescape
和throws
,它们的原型更加清晰:
public func map<U>(f: Wrapped -> U) -> U?
public func flatMap<U>(f: Wrapped -> U?) -> U?
在这两个泛型函数中,Wrapped
是Optional的泛型参数,即Optional包裹的类型。两个函数唯一的不同是接收的参数「函数的返回值」不同,一个期待函数返回U
,另一个期待函数返回U?
。
两个函数在表现上是类似的,如果可选类型有值(!= nil),则返回f(Wrapped Value)
,否则直接返回nil。
那么不难理解前面的例子:
let url:NSURL? = avatarURL.flatMap {
return NSURL(string: $0) // NSURL? 相当于 U?
}
let nothing:Optional = url.map {
print($0.absoluteString) // 什么都不返回,因此这个map返回一个什么都不包裹的Optional
}