SpriteBuilder代码中弱引用(weak)需要注意的地方

比如在GameScene类中有一个弹出菜单层实例的引用,我们有:

@implementation GameScene{
//other ivars
__weak GameMenuLayer *_popoverMenuLayer;
}

//other methods
@end

下面创建一个弹出菜单层的方法:

-(void)showPopoverNamed:(NSString *)popoverName{
    if (!_popoverMenuLayer) {
        GameMenuLayer *newMenuLayer = (GameMenuLayer*)[CCBReader load:popoverName];
        NSAssert(newMenuLayer, @"newMenuLayer must not nil!!!");
        [self addChild:newMenuLayer];
        _popoverMenuLayer = newMenuLayer;
        _popoverMenuLayer.gameScene = self;
        _gameMenuLayer.visible = NO;
        _levelNode.paused = YES;
    }
}

该段代码中第一个件判断if语句确保任何时刻只能有一个可见的弹出菜单层,甚至当该方法被意外连续运行2次也能确保如此.

代码逻辑很好懂,不懂也没关系;重要的是你可能会奇怪”为毛不直接将弹出菜单层的引用直接赋给_popoverMenuLayer,从而删除局部变量newMenuLayer?”

揭晓原因!!!因为_popoverMenuLayer被声明为弱引用,所以它不会保留赋给它的任何引用.当CCBReader load:方法返回时,即使仅有那么”一刹那”;没有强引用可以保留返回的节点.因此ARC将会release该(返回的)节点并且将_popoverMenuLayer赋值为nil,甚至在这之后立即调用addChild:方法也不行!

再明确的说:在debug配置中这种情况可能会也可能不会工作,取决于设备的debug配置;但是它在release配置中肯定不能工作!

再多说一点,我建议在addChild:方法代码前面添加NSAssert宏去验证newMenuLayer的值不为nil.这是因为popover可能在一个不同的文件夹中,可能CCB文件的名字输错了,或者仅仅是CCB文件还未被建立或已经建立但尚未published.
这些经常出错的问题,并不仅仅会在这个示例游戏代码中出现.所以一个好注意是尽可能早的抓住它们!(It’s a good idea to try and catch those early.)

上一篇:数据湖实操讲解【 JindoTable 计算加速】第十九讲:Spark 对 OSS 上的 Parquet 数据进行查询加速


下一篇:数据湖实操讲解【JindoFS 缓存加速】第十四讲:指定表和分区来预先缓存,查询分析更高效