21
20

More than 5 years have passed since last update.

なぜdelegateはunowned(unsafe)+Implicitly Unwrappedなの?

Posted at

またも机上の空論で投稿を書いてしまった。。。
仕事が忙しくなると逃避したくなるよね。

疑問1 なぜImplicitly Unwrappedなのか?

Implicitly Unwrappedはdelegateがnilの場合に危険なので、普通のOptionalで使った方が安全に思われます。でも、そもそもunowned(unsafe)定義をしている時点で、nilチェックしても安全性はチェックできません。

そもそも「初期化後にnilである可能性がある」場合には、unownedではなく、weakを使うべきです。つまり正しい組み合わせは下記の二つです。

  • weak + Optional
  • unowned(unsafe) + Optional Implicitly Unwrapped

The Swift Programming Language

Use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialization.

疑問2 なぜweakじゃなくてunowned(unsafe)なのか?

本来の趣旨からいけば、初期化時のパラメタとして与える必須のdelegateについてはunowned、後から設定できるoptionalなdelegateはweakにするのが正しいように思われます。前者の例はUIAlertView、後者の例はUITextViewなどですね。

Cocoaではすべてのdelegateがunownになっているようですが、これはフレームワークとしてはARCが無い場合にも対応したいからでしょうか。誰かご存知ですか?

疑問3 Implicitly Unwrappedはいつ使うのか?

これには、Two-Phase Initializationが関係してきます。
Swiftの初期化において、第一フェーズが終わりすべての変数に初期値が設定されるまでは、そのインスタンスは使用する事ができません。

ここで、AとBが相互参照するケースを考えると、AはBの初期化が完了するまでBを参照できず、BはAの初期化が完了するまでAを参照できません。これを回避するため、AからBの参照をOptionalとし、nilで初期化することでAの初期化を完了させます。これでAの参照が使用できるようになるので、これを用いてBを初期化します。最後に、初期化が完了したBをAから参照します。

この場合、どちらか一方は弱参照にしないと循環参照となるため、一方をunowned(unsafe)に設定する必要があります。これが、unowned(unsafe)+Implicitly Unwrappedの正しいユースケースのようです。

21
20
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
20