0

ARCリリースノートへの移行によると、ブロック内で自分自身を参照する場合は、強い参照/保持サイクルを回避するために弱い参照を使用する必要があります。

MyViewController *myController = [[MyViewController alloc] init…];
// ...
MyViewController * __weak weakMyController = myController;
myController.completionHandler =  ^(NSInteger result) {
MyViewController *strongMyController = weakMyController;
if (strongMyController) {
    // ...
    [strongMyController dismissViewControllerAnimated:YES completion:nil];
    // ...
}
else {
    // Probably nothing...
}
};

時々、ブロック内で自分自身を参照すると保持サイクルが発生する可能性があるというコンパイラの警告が表示されます。警告がないということは、保持サイクルが作成されないことを意味しますか?警告が保持サイクルにつながる可能性が高いと見なされるのはなぜですか?

4

1 に答える 1

3

警告がないということは、保持サイクルが作成されないことを意味しますか?

いいえ。コンパイラは、保持サイクルを作成できる特定の条件を判別できますが、保持サイクルを作成する可能性を排除することはできません。例として、次のクラスについて考えてみます。

@interface MyClass : NSObject

@property (readwrite, strong) id myObject;

@end

および別のクラスのコードフラグメント:

MyClass *one = [MyClass new];
MyClass *two = [MyClass new];

one.myObject = two;
two.myObject = one; // created a strong cycle...

コンパイラがこの単純なサイクルを見つけるには、複数のクラスにわたるフロー分析が必要であり、一般に、この問題はコンパイラでは解決できません(実行時にサイクルの作成をスキャン/スポットできますが、ARCはこれを行いません)。

警告が保持サイクルにつながる可能性が高いと見なされるのはなぜですか?

サイクル自体を作成すること自体は間違っていたり悪いことではありません。サイクルは、孤立した場合にのみ問題になります。つまり、ライブ参照はそれを参照せず、サイクル内のオブジェクトを存続させるのは循環参照のみです。

コンパイラは、作成中のブロック内で自分自身への強い参照を確認すると、ライブの強いサイクルが作成されることを認識しますが、ブロックが不要になる前にそのサイクルが後で中断されるかどうかを判断できません(つまり、上記のように一般的に解決できません)。または、作成中のオブジェクトとブロックが孤立したサイクルを形成するかどうか。したがって、非決定的な「可能性が高い」の使用。

于 2012-11-12T09:15:15.307 に答える