Swiftの循環参照問題におけるunownedとweakの使い分けについて


## はじめに

前回の記事 [Swiftのクロージャにおける循環参照問題でunownedとweakの使い分けがわからない](http://qiita.com/susieyy/items/39efd4d34cf4c1f9d3ef) にて、unownedとweakの使い分けがわからない旨を記載したところ、多くの方よりコメント欄で助言を頂いたので、その内容を踏まえてこちらに新たに記事として記載しました。コメントをくださった皆様ありがとうございました。ご指摘がありましたらコメントにてお寄せください。

## 補足

こちらにまとめる情報は私の個人的な見解によるまとめです。コメント欄に助言頂いた方の総意ではないので、[前回の記事](http://qiita.com/susieyy/items/39efd4d34cf4c1f9d3ef)のコメント欄も合わせてご参照頂くことをお薦めします。本来なら前回の記事に追記すべきですが、新規で読まれた方が追記だらけで読みにくくなりそうなので記事を分けさせてもらいました。

## unownedとweakの使い分けの判断


|項番|循環参照|対象の変数をweakで対応し<br />実行時に変数がnilになる可能性|対応|
|----|----|----|----|
|#1|しない|---|unowned、weakは記述しない<br / >対象の変数は強参照扱い　(strong)|
|#2|する|あり|weakを記述する|
|#3|する|なし|1.weakを記述する<br />2.unownedを記述する<br />weakとunownedのどちらで記述するかはエンジニアの判断|


### 循環参照するか、しないかの切り分け

循環参照するか、しないかの切り分けはエンジニアが考慮する必要があります。この切り分けはObjCと同様なので、ここでは詳細には触れません。

ちなみに、Xcode6 Beta5のSwiftではコンパイルワーニングで循環参照を知らせてくれません。とはいえ循環参照のコンパイルワーニングはObjCでも全部網羅されていないので、最終的にはエンジニアが考慮する必要があるのはかわらないのですが。

### 対象の変数をweakで対応し、実行時に変数がnilになる可能性の切り分け

そもそも、実行時に循環参照する対象の変数がnilになる可能性で判断ではなく、対象の変数定義がOptional定義かどうかで判断できないか

常にOptional定義かどうかで判断できないのではと思っています。例えば`self`は`self!`としてunwrapしてアクセスしないので、`self`はOptionalではないと思いますが、非同期のコールバックや遅延実行を絡めたクロージャでは`self`が先に解放される場合があります。これは変数にnilが代入されたというよりも、変数が存在しなくなったのでnilと同義になったと言えるのではと思います。つまり、変数にnilが代入されるということと、変数が解放されnilになるのは同じnilの状態ですが区別する必要があり、この両方の遷移によるnilを考慮した対応をする必要があるためOptional定義だけで判断するのは片手落ちになってしまうと思います。

よって、weakとunownedの判断は循環参照する対象の変数がnilになるのかどうかをケースバイケースで考慮する必要があります。これはObjCのころのBlockにおける循環参照の対象となる変数がnilになる可能性を考慮する問題と同じです。


### weakとunownedのどちらで記述するかの判断

weakとunownedのどちらで記述するかはエンジニアの判断によりますが、『実行時に対象の変数がnilになる可能性の切り分け」が難しい部分もあるので、エンジニアの熟練度やチームでの合意に応じてポリシーを決めればよいのではと思います。よって、どちらが正しいと言うものでもないと思っています。

|引用項番|ケース|参照方式|メリット|デメリット|
|----|----|----|----|----|
|#3-1.|weak|弱参照|循環参照の場合、常にこの記述方法で対応できる|合わせてif letでunwrapの記述が常に必要<br />unownedで記述できる場合はunwrapの記述が冗長になる|
|#3-2.|unowned|弱参照|クロージャ内で対象の変数がnilにならないことを明記できる<br />unwrapの記述が不要|対象の変数がnilだった場合にクラッシュする|

## AppleのSwiftドキュメントでは？

[The Swift Programming Language - Automatic Reference Counting - 
Resolving Strong Reference Cycles Between Class Instances](https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-XID_93)

> 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.

[The Swift Programming Language - Automatic Reference Counting - Unowned References](https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-XID_96)


>If you try to access an unowned reference after the instance that it references is deallocated, you will trigger a runtime error. Use unowned references only when you are sure that the reference will always refer to an instance.

>Note also that Swift guarantees your app will crash if you try to access an unowned reference after the instance it references is deallocated. You will never encounter unexpected behavior in this situation. Your app will always crash reliably, although you should, of course, prevent it from doing so.


## 助言くださった方

助言くださった皆様ありがとうございます。(コメント順）

- @tomohisaota さん
- @takabosoft さん
- @satoshia さん
- @corosuke_k さん

## 修正 ８月２７日 ２３時

誤解を招く言葉足らずのところを修正しました。
循環参照の対象の変数はstrongでキャプチャしているので、nilになることはありません。
ここでいう実行時に対象の変数がnilになる可能性とは、循環参照の変数をweakで扱った場合です。

【修正前】実行時に対象の変数がnilになる可能性の切り分け
↓
【修正後】対象の変数をweakで対応し、実行時に変数がnilになる可能性の切り分け