Swift で 2回 Unwrap が必要なケースについて調べた

  • 10
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

検証環境:Xcode6.1, Swift1.1


例えば以下の様な Objective-C のコードを

[[[UIApplication sharedApplication] delegate] window].rootViewController

Swift で書き直そうとした場合、まずはこんな感じに書くと思う。

UIApplication.sharedApplication().delegate?.window?.rootViewController

しかしこれだとコンパイルエラーになる。

スクリーンショット 2014-11-15 16.46.51.png

そしてどういうことか、window? に更に Unwrap を行うことでコンパイルが通るようになる。

UIApplication.sharedApplication().delegate?.window??.rootViewController

この意味が全くわからなかったので調べたところ StackOverFlow に検証エントリーを見つけたので、まずはこちらを見て頂くと良いと思う。

http://stackoverflow.com/questions/26201456/unwrap-uiwindow-twice-from-appdelegate-in-swift

検証コード

先に挙げた記事のコードを引用させていただく。

import Foundation

@objc protocol MyApplicationDelegate {
    optional var myWindow: MyWindow? { get set }
}

class MyWindow : NSObject {
    var rootViewController: Int?
    init(number: Int) {
        rootViewController = number
    }
}

class MyAppDelegate: MyApplicationDelegate {
    var myWindow: MyWindow?
    init() {
        myWindow = MyWindow(number: 5)
    }
}

class MyApplication: NSObject {
    var myDelegate: MyApplicationDelegate
    override init() {
        myDelegate = MyAppDelegate()
    }
}

let myApplication = MyApplication()
println(myApplication.myDelegate.myWindow??.rootViewController)

1つ目のポイントは protocol の定義

    optional var myWindow: MyWindow? { get set }

MyWindow の optional 型プロパティ自体を optional 扱いで定義している。

2つ目のポイントは MyApplication の定義

    var myDelegate: MyApplicationDelegate

myDelegate の型を MyApplicationDelegate で定義している。

MyApplication を使わない方が自分的に分かりやすかったので、以下の様なコードでも検証してみた。

var delegateA :MyApplicationDelegate
delegateA = MyAppDelegate()

// Unwrap が2回必要
delegateA.myWindow??.rootViewController

if let delegateB = delegateA as? MyAppDelegate {
    // Unwrap 1回で良い 
    delegateB.myWindow?.rootViewController
}

結論

継承している protocol の型でクラスを保持している場合、その protocol に optional で実装定義されているものが実装されている保証が無い。そのため、optional実装定義されているものに対して Unwrap が必要になる様だ。

さらにその optional 実装定義されたものの型が optional型だった場合は当然 Unwrap しないといけない。

上記の様なケースの場合、 2回 Unwarp が必要になる と理解しました。

間違いなどありましたらコメント頂けると幸いです。