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;

将节点添加为子节点后,子数组将持有对该节点的强引用。因此,在 addChild: 行之后,您可以将临时 bg 节点分配给 _background ivar。

于 2014-10-30T13:00:41.043 回答
1

内存管理没有硬性规则。您需要查看您的代码并决定使用的最佳方法。

在你的情况下,虽然你只有一个背景,你可以让那个属性变弱。Cocos2d 拥有对场景图中所有节点的强引用,因此它会为您保留它。

这并不意味着每个节点都应该存储为弱节点,有时如果节点不在场景图中,您希望节点在周围徘徊。

于 2014-10-30T10:20:09.487 回答