IOSによくある循環引用のまとめ

1500 ワード

IOSによくある循環引用のまとめ
紹介:
循環参照とは、複数のオブジェクトが相互参照している場合、参照が環状になり、外部がこのリングメモリを本当に落とすことができなくなることを意味します。実はちょっとロックみたいです。
例を挙げると、A->B->C->….->X->B   ->このようなBの参照カウントは2です。Aがシステムから解放されたら、理論的にAが自動的にAから引用されたリソースを減らすのがBです。Bの参照カウントは1になり、Bはすべて解放されません。しかし、Aはすでに解放されました。Bのメモリ部分は必ず再利用できなくなり、メモリが漏れてしまいます。
状況一:delegate
Delegateはios中開発の中で最もよく出会う循環引用で、一般的にdelegateを宣言する時は弱引用weakまたはassignを使います。

@property (nonatomic, weak, nullable) id <UITableViewDelegate> delegate;
もちろん、assignを使うかweakを使うかどうかを選択します。MRCはassignしか使えません。ARCの場合はweakを使ったほうがいいです。weak修飾の変数は後に自動的にnilを指すので、安全ではない野針が存在しないようにします。
状況二:ブロック
Blockも比較的によくある循環引用問題で、Blockの中でselfを使って循環参照が現れやすいので、多くの人がblockを使う時、中に入れてselfの操作に役立つと、一つの_u u u u uを宣言します。weakはselfを修飾します。実はこのようなのではなくて、Blockを使ってすべてSelf循環引用問題が現れるのではなくて、selfだけがBlockの強い引用を持っていてこのような情況が現れます。
したがって、一般的には、Blockを関数に一時的に使用すると、ループアプリケーションは発生しません。この場合、Block参照はスタックに属します。スタック上のblockが解放されると、blockの中のselfに対する参照カウントも減少します。
もちろん、SelfはBlockに対して直接的な参照があるとは限りません。もしselfの変数Bであれば、BにBlock変数があると、このような状況が起こりやすくなります。良いのは、ブロックに循環参照が現れ、xcode 7に警告メッセージが表示されます。
状況三:NSTimer
これは、NSTimerを作成する際にNSTimerを使用すると、NSTimerは現在のselfに対して強い引用がデフォルトになります。selfで使用する予定があるかどうかは、まずNSTimerのinvalidateを使用して、selfへの参照を制限してください。

[_timer invalidate];
まとめ:
上で述べたのは私達のよくあるので、実は循環引用は私達の強引用が閉ループを形成して、また多くの自分で書いたコードの中で現れることができて、ふだんやはり書き方に注意します。もちろんxcodeのinstrumentsもこのようなメモリの問題を排除するのに役立ちます。
読んでくれてありがとうございます。みなさんのご協力をお願いします。ありがとうございます。