a: A??
を要領よくアンラップしたい
let a: A??
if let z = a ?? nil {}
元ネタ:
@cocoaphony let w: UIWindow? = app.delgate?.window?? nil
That is my approach for double optionals in 1.2. (trailing ? works in 1.1.)
解説
シンタックスシュガー ?
や ??
があるとわかりにくいので外す
それぞれの定義は以下
// ? (Optional)
// https://github.com/apple/swift/blob/7ed7354003406c8e4a708195b86c1950b2c1f381/stdlib/public/core/Optional.swift#L122-L133
enum Optional<T> {
case none
case some(t: T)
}
// ?? (Nil-Coalescing Operator)
// https://github.com/apple/swift/blob/7ed7354003406c8e4a708195b86c1950b2c1f381/stdlib/public/core/Optional.swift#L655-L663
public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T)
rethrows -> T {
switch optional {
case .some(let value):
return value
case .none:
return try defaultValue()
}
}
処理の中身を見ていく
// 以下の二行は同義
let a: A??
let a: Optional<Optional<A>>
// この文を分解していく
if let z = a ?? nil {}
// ?? と if-let に分離
let b = a ?? nil // ①
if let z = b {} // ②
// ①から見ていく
// a は Optional<Optional<A>> であるので、?? (Nil-Coalescing Operator) のジェネリック型 T は Optional がひとつ外れた Optional<A> である
// ということは右辺の nil は Optional<A>.none であることがわかる
// つまり b は Optional<A> である
let b: Optional<A> = a ?? nil
// あとは②に入れるだけ
if let b = z {} // z: A?