質問: を読んでいると `OperationQueue`に渡している`resultHandler`は`@escaping`が付いていないことに気づきました。`OperationQueue`は普段使っていないので、あまり詳しくはないのですが、ネットワーク通信ですので、`@escaping`と`[weak self]`をセットで使うのが安全と考え、検索したところ、 の回答を見つけました。 私の回答理解としては、 `OperationQueue`はメモリーリークは起こらず、いい感じに取り扱ってくれるので、`@escaping`と`[weak self]`はいらないというように読めたのですが、 なぜ`@escaping`と`[weak self]`はいらないのかという疑問は残ったままとなりました。なにか理由があるとかいうわけではなく、Appleがそう作ったからという結論になってしまうのでしょうか?
回答: ***`@escaping`と`[weak self]`をセットで使うのが安全*** まず1点目に強く強調しておきたいのは、`@escaping`を付けるべきかどうかと、`[weak self]`を使うべきかどうかとは全く別の問題だと言うことです。 * `@escaping` 引数として渡したクロージャーがどこかに保存され、メソッドが終了した後に呼び出される可能性がある場合につけます。目安としては、**Swiftがこの引数については`@escaping`をつけないとコンパイルしてあげないと言わない限りつけない方が良い**、と言うところになります。 * `[weak self]` クロージャーがインスタンス変数に保存されるなどで、循環参照(retain cycle)が発生する可能性のある場合に、それを避けるためにつけます。目安としては、**どんな場合に循環参照になるのかようわからんならとりあえず`[weak self]`は付けときなさい。あんまわかってない人は`[unowned self]`は決して使っちゃダメ**、と言ったところ。 その上でリンク( )先コードのパラメータに`@escaping`が付いていないのは、「現在のSwiftではOptionalのクロージャー型は暗黙のうちに`@escaping`と解釈されるから」です。決して、「(`OperationQueue`が)いい感じに取り扱ってくれる」からではありません。 こちら( )の回答に関しては読み方がかなり誤っています。 > > You do have a retain cycle there, but that doesn’t automatically lead > > to a memory leak. After the queue finished the operation it releases > > it thus breaking the cycle. > > > (拙訳) > > そいつは実際循環参照になるんだよ。ただ、それが直接メモリリークになるとは限らないんだ、キューがオペレーションの実行を終えると、そのオペレーションは解放されるんで循環参照もなくなるからね。 > > > と言うわけで、`OperationQueue`を使ったって循環参照は発生します。 さらにこんなことも書いてあります。 > > As an experiment you can suspend the queue. Then you will see the > > memory leak. > > > 試しにキューをサスベンドしてごらん。そしたらメモリリークするのがわかるから。 > > > と言うわけで、`OperationQueue`絡みの循環参照がメモリリークに繋がることはあり得ます。「いい感じに取り扱ってくれる」と言った認識しか持てない人(正直iOSプログラミングについてはいろいろ心に留めておかなければならないことがたくさんありますから、この程度の認識でアプリ作りをする、と言うのも多分ありだとは思います)は、`[weak self]`をつけといた方が良い、と言えます。 じっくり時間をかけて解析したわけではないですが、リンク先のコードで`resultHandler`に渡すクロージャーでは循環参照が発生し得ます。ざっくりコードを眺めた限りでは、必ず解消されるから気にしなくて良い、と言ったコードにはなっていません。