4

多数の子ノードを持つカスタムCCNodeクラスがあり、いくつかのカスタム トランジションを作成するために、子への参照を保持したいと考えています。

たとえば、子の背景の場合、カスタム クラスは次のようになります。

@interface MyNode : CCNode
@property (nonatomic, strong) CCNode *background;
@end

@implementation
- (void)setBackground:(CCNode *)background {
    if (_background) {
        [self removeChild:_background];
    }
    if (background) {
        [self addChild:background];
    }
    _background = background;
}
- (void)runTransition {
    if (_background)
        [_background runAction:[…]];
}
@end

問題は、これにより ARC で保持サイクルが発生し、ノード バックグラウンドがメモリから解放されないことです。

4

2 に答える 2

1

インターフェイスを変更して、ゼロ化の弱参照を使用します。

@interface MyNode : CCNode
@property (nonatomic, weak) CCNode *background;
@end

バックグラウンド ノードの割り当てが解除されると、_background ivar は自動的に nil になります。そうすれば、保持サイクルがなくなります。ノードの子または孫であるノードにノード参照を格納する場合、これは一般的に良い方法です。これらの状況では常に保持サイクルが発生するためです。

そのままのコードは、弱い参照で正常に動作するはずです。

ただし、弱参照を作成して代入するときは注意が必要です。たとえば、これは nil ノードが子として追加されると失敗します。

_background = [CCNode node];
[self addChild:_background];

ここでの問題は、割り当ての後、バックグラウンド ノードを強く保持するものが何もないため、割り当てが解除され、addChild: 行の前で nil に設定されることです。

簡単な回避策があります:

CCNode* bg = [CCNode node];
[self addChild:bg];
_background = bg;

ノードが子として追加された後、children 配列はノードへの強い参照を保持します。したがって、addChild: 行の後に、一時的な bg ノードを _background ivar に割り当てることができます。

于 2014-10-30T13:00:41.043 に答える