2013-04-17 6 views
10

私はこのようなブロック内でグローバルVARまたはプロパティを使用する必要がありますたびに、「このブロックで強くキャプチャ自己保持のサイクルにつながる可能性があります」このようなそれもBOOL変数文句メッセージ

BOOL *iis = isItSaving; 
id myself = self; 

self.save = ^(){ 
    if (iis == NO) { 
     [myself saveMyFile]; 
    } 
}; 

やXcodeのは、保持サイクルにつながる可能性があり、このブロックで強く自己を捉える」文句を言うだろう...?

ブロックが不自由な解決策の前にすべてを再宣言します。

これは正しい方法ですか?エレガントな方法はありますか?

このものは醜いです。私はARCを使用しています。

答えて

20

この問題は、明示的または暗黙的にブロック内からselfを参照する場合にのみ発生します。グローバル変数にアクセスするときに警告は表示されません。

あなたのケースでは、おそらく(ブール)ivarにアクセスしました。 ivarにアクセスすると暗黙的にselfが使用されるため、コンパイラは保持サイクルについて(正しく)警告します。

保持サイクルを修正する一般的な方法は次のとおりです。

typeof(self) __weak weakSelf = self; 

self.save = ^() { 
    typeof(weakSelf) __strong strongSelf = weakSelf; 
    if (strongSelf != nil && ! strongSelf->isItSaving) { 
     [strongSelf saveMyFile]; 
    } 
}; 

...そして、はい、それはブロックの醜い部分のビットです。あなたの例では

+1

男、これは地獄のように醜いです。すべてを再宣言しなければならない...ありがとう。 – SpaceDog

+0

@MarkAmeryはい、clangはますます多くの問題を抱えています。そして、正しいことですが、囲みオブジェクトの寿命は、少なくともブロックが終了するまで延長する必要があります。編集中... –

+1

@NikolaiRuhe * "囲みオブジェクトの寿命は、少なくともブロックが終了するまで延長する必要があります" * - nice、ブロック内の 'self'への強い参照を作成する理由は何も気づきませんでした'__unsafe_unretained'を使用するよりも好ましいでしょうが、そのフレーズだけで信じられないほど明確になります。もしあなたが望めば、答えの中の2つのアプローチを比較する価値があるかもしれません。 –

4

使用NikolaiRuheの応答@に加えて__unsafe_unretained typeof(self) weakSelf = self;

+0

ARCで__unsafe_unretainedを使用することはできないと思います – SpaceDog

0

、プロパティ

BOOL *iis = isItSaving; 
id myself = self; 

を宣言strongの参照を意味し、その保持サイクルを防ぐために__weak自己を使用しています。それでブロック内の弱い自己への参照をなぜ__strongと宣言する必要があるのだろうかと疑問に思うかもしれません。そうでなければ、selfが解放されたときにweakSelf->isItSavingが壊れてしまいます。