block __weak __strong修飾子の使用

1500 ワード

Objective CのBlockは実用的な構文で、特にGCDと組み合わせて使用すると、同時、非同期のタスクを容易に実現できます.しかし、適切に使用しないと、Blockはいくつかの循環参照問題(retain cycle)--Blockはretain‘self’を引き起こし、‘self’はまたretain Blockを引き起こす.ObjCでは、インスタンス変数を直接呼び出すと、コンパイラによって「self->theVar」として処理され、「self」はstrongタイプの変数であり、参照カウントに1が加算されるため、self retains queue,queue retains block,block retains selfとなる.
retain circleの解決
Appleの公式の提案は、Blockに伝わる前に「self」をweak automaticの変数に変換し、Blockでselfへの強い参照が現れないことだ.Blockの実行が完了する前にselfが解放されるとweakSelfもnilになります.
サンプルコード:
__weak__typeof__(self)weakSelf=self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
     [weakSelfdoSomething];
});

clangのドキュメントは、doSomething内でweakSelfが解放されないことを示しています.ただし、次の場合を除きます.
__weak__typeof__(self)weakSelf=self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
    [weakSelfdoSomething];
    [weakSelfdoOtherThing];
});

doSomethingではweakSelfはnilにはなりませんが、doSomethingの実行が完了し、2番目のメソッドdoOtherThingを呼び出すとweakSelfが解放される可能性があり、strongSelfが役に立ちます.
__weak__typeof__(self)weakSelf=self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
       __strong__typeof(self)strongSelf=weakSelf;      
       [strongSelfdoSomething];     
       [strongSelf doOtherThing];
});

__strongはBlock内でstrongSelfが解放されないことを保証する.
まとめ
Block内でselfのメソッド、変数にアクセスする必要がある場合はweakSelfを使用することをお勧めします.
Block内でselfに複数回アクセスする必要がある場合はstrongSelfを使用する必要があります.