10

これは、XCode を 4.6 に更新したときにのみ表示される新しいコンパイラ警告です。私のコードは、Apple のドキュメントから直接引用されています (これは私の iOS 6 コードです)。

GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];

localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
    [self setLastError:error];
    if(localPlayer.authenticated){

警告 -- このブロックで「localPlayer」を強力にキャプチャすると、保持サイクルが発生する可能性があります

4

2 に答える 2

25

問題は、localPlayer オブジェクトがそれ自体への強い参照を保持していることです。あなたのために)。現在、localPlayer への他のすべての参照が存在しなくなった場合でも、保持カウントは 1 のままであるため、メモリが解放されることはありません。これが、コンパイラが警告を発している理由です。

次のような弱参照で参照してください。

GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];

__weak GKLocalPlayer *blockLocalPlayer = localPlayer;
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
    [self setLastError:error];
    if (blockLocalPlayer.authenticated) {
        ...

authenticateHandler と localPlayer の有効期間が密接にリンクされている場合 (つまり、localPlayer の割り当てが解除されると、authenticateHandler も同様に関連付けられます)、authenticateHandler 内で強力な参照を維持する必要はありません。Xcode 4.6 を使用すると、前述の警告は生成されなくなりました。

于 2013-01-30T23:14:21.580 に答える
1

コンパイラーは、すでに問題になっているコードを支援しているだけで、以前はそれについて知りませんでした。

ここで保持サイクルについて読むことができます:http://www.cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html

基本的には、コードを次のように変更する必要があります。

GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];

__weak MyViewController *blockSelf = self;
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
    [blockSelf setLastError:error];
    if(localPlayer.authenticated){
于 2013-01-30T22:36:01.570 に答える