Swiftになってからもメモリリークは気をつけなければならない問題だ。
そして、メモリリークが起きやすい原因の一つとして循環参照がある。

循環参照を避けるためにはunownedやweakを使うのだが、今回はクロージャが入れ子になっている場合について調べてみる。
 
簡単な循環参照の例
まず以下の様なクラスを用意する。

そして、これを外部から以下のように実行する。

循環参照が発生しているため、testインスタンスはスコープを抜けても解放されない。
予定通りだ。

次に、循環参照を回避するためにTestClassを以下のようにする。

[unowned self]を指定しているため、循環参照は発生せず、deinitがちゃんと呼ばれるようになる。
ここまではよくある話だ。

クロージャが入れ子の場合
ではクロージャが入れ子になる場合はどうだろう。
まず、TestClassに以下のメソッドを追加する。

これを入れ子にして呼び出してみよう。
init()を以下のようにする。

実行してみると、出力は問題なく行われ、deinitもちゃんと呼び出された。
anotherFuncの中で使用しているselfにもunownedがちゃんと効いてるようだ。

ちなみに、anotherFuncの呼び出し時に[unowned self]を書いたらどうなるだろう。

特に問題が起こることはなく、上記と同じ結果が得られる。

しかし、別のプロジェクトでこのように[unowned self]を二重にした際に以下のようなエラーが発生したことがあった。

Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1

これに関しては他のプロジェクトで再現することが出来なかったため詳細はわからない。
しかし、[unowned self]が二重になっているのを修正したら解決したので、[unowned]は二重にならないようにしておいたほうが良さそうだ。