Pointers Cocos2d:可以使用指向父对象的指针吗';s类指针?

Pointers Cocos2d:可以使用指向父对象的指针吗';s类指针?,pointers,opengl-es,cocos2d-iphone,ccsprite,Pointers,Opengl Es,Cocos2d Iphone,Ccsprite,愚蠢的问题。Cocos2d是围绕父子层次结构构建的。我想知道是否可以拥有一个父类(例如GameSecene)并使用指向父类成员(例如CCSpriteBatchNode*)的指针初始化一个子类(例如SpriteHandler) 我尝试这样做是为了优化ccspritebatch节点的数量。下面是我的主类(游戏场景风格)的代码片段 可以这样做,但如果使用ARC,则应将SharedPriteBatchNode设置为弱指针。如果不这样做,您可能会得到一个循环引用 循环引用将发生的情况是,当导演在运行完游戏

愚蠢的问题。Cocos2d是围绕父子层次结构构建的。我想知道是否可以拥有一个父类(例如GameSecene)并使用指向父类成员(例如CCSpriteBatchNode*)的指针初始化一个子类(例如SpriteHandler)

我尝试这样做是为了优化ccspritebatch节点的数量。下面是我的主类(游戏场景风格)的代码片段


可以这样做,但如果使用ARC,则应将SharedPriteBatchNode设置为弱指针。如果不这样做,您可能会得到一个循环引用


循环引用将发生的情况是,当导演在运行完游戏场景后释放你的游戏场景时,你的游戏场景仍将让你的孩子保留它,而你的游戏场景仍将保留该孩子。此圆将浮动,并且永远无法释放,因为它已被放弃。

您可以这样做,但如果使用ARC,则应将sharedSpriteBatchNode设置为弱指针。如果不这样做,您可能会得到一个循环引用


循环引用将发生的情况是,当导演在运行完游戏场景后释放你的游戏场景时,你的游戏场景仍将让你的孩子保留它,而你的游戏场景仍将保留该孩子。这个圆圈将漂浮,永远无法释放,因为它被遗弃了。

本说了什么。它不应该是保留引用或强引用,后者是ARC中的默认值,例如变量

有一种方法可以确保在ARC下,即使使用强引用,也可以保持循环安全。覆盖清除方法并在此处取消引用(如果保留引用,则在MRC下也应在此处调用release):

在Dealoc中这样做是行不通的。只要子节点具有对父节点的强引用,它就不会被解除分配。因此,您需要在cleanup中执行此操作,并确保可以设置cleanup标志的所有方法调用都将该参数设置为YES

但还有其他解决方案,我认为比在初始值设定项中传递父节点更好。例如,您可以通过父级的公共标记获取共享批处理节点,并在每次需要时执行该操作(将其包装为一个小函数)或将其存储在弱(非保留)实例变量中:

// onEnter is typically called right after init (during addChild)
// parent is already set here
-(void) onEnter
{
    [super onEnter];

    CCSpriteBatchNode* sharedBatchNode = [parent getChildByTag:kSharedBatchNodeTag];
}
或者获取父类并强制转换它,假设sharedBatchNode是父类的属性:

-(void) whereEver
{
    ShooterScene* scene = (ShooterScene*)parent;
    CCSpriteBatchNode* sharedBatchNode = scene.sharedSpriteBatchNode;
    …

    // you can also reduce the above to a single line:
    CCSpriteBatchNode* batch = ((ShooterScene*)parent).sharedSpriteBatchNode;
}

尤其推荐后一种解决方案。即使您经常需要这样做,它也很快。铸造是免费的,财产访问不超过一个消息发送。只需确保父对象实际上是您要将其投射到的类的对象。

本所说的。它不应该是保留引用或强引用,后者是ARC中的默认值,例如变量

有一种方法可以确保在ARC下,即使使用强引用,也可以保持循环安全。覆盖清除方法并在此处取消引用(如果保留引用,则在MRC下也应在此处调用release):

在Dealoc中这样做是行不通的。只要子节点具有对父节点的强引用,它就不会被解除分配。因此,您需要在cleanup中执行此操作,并确保可以设置cleanup标志的所有方法调用都将该参数设置为YES

但还有其他解决方案,我认为比在初始值设定项中传递父节点更好。例如,您可以通过父级的公共标记获取共享批处理节点,并在每次需要时执行该操作(将其包装为一个小函数)或将其存储在弱(非保留)实例变量中:

// onEnter is typically called right after init (during addChild)
// parent is already set here
-(void) onEnter
{
    [super onEnter];

    CCSpriteBatchNode* sharedBatchNode = [parent getChildByTag:kSharedBatchNodeTag];
}
或者获取父类并强制转换它,假设sharedBatchNode是父类的属性:

-(void) whereEver
{
    ShooterScene* scene = (ShooterScene*)parent;
    CCSpriteBatchNode* sharedBatchNode = scene.sharedSpriteBatchNode;
    …

    // you can also reduce the above to a single line:
    CCSpriteBatchNode* batch = ((ShooterScene*)parent).sharedSpriteBatchNode;
}

尤其推荐后一种解决方案。即使您经常需要这样做,它也很快。铸造是免费的,财产访问不超过一个消息发送。只需确保父对象实际上是您要将其投射到的类的对象。

谢谢Steffen,回答得又好又清楚。有很多我没有考虑过的想法。谢谢你,Steffen,回答得很清楚。有很多我没有考虑过的想法。谢谢Ben,有趣的回答。我以后会考虑这个问题。我投了更高的票,但接受了LearnCos2D one,因为它为我的问题提供了一个“创新”的解决方案,但公平地说,你的答案也应该被接受,并且两者都应该被考虑。你应该始终接受最有帮助的答案。我同意,史蒂芬的回答比我的好,他活该!我非常感激能够向如此广泛和有帮助的社区(如so)提出问题。谢谢分享你的知识。我希望,一旦我发布了我的第一个游戏,我会知道足够多的知识来帮助你们,就像你们一样:)。谢谢本,有趣的回答。我以后会考虑这个问题。我投了更高的票,但接受了LearnCos2D one,因为它为我的问题提供了一个“创新”的解决方案,但公平地说,你的答案也应该被接受,并且两者都应该被考虑。你应该始终接受最有帮助的答案。我同意,史蒂芬的回答比我的好,他活该!我非常感激能够向如此广泛和有帮助的社区(如so)提出问题。谢谢分享你的知识。我希望,一旦我发布了我的第一个游戏,我能像你们一样了解到足够的帮助:)。
-(void) whereEver
{
    ShooterScene* scene = (ShooterScene*)parent;
    CCSpriteBatchNode* sharedBatchNode = scene.sharedSpriteBatchNode;
    …

    // you can also reduce the above to a single line:
    CCSpriteBatchNode* batch = ((ShooterScene*)parent).sharedSpriteBatchNode;
}