iOS Cocos2d CCLabelTTF设置字符串以Exc错误访问结束



在开发iPhone游戏的过程中,这花费了我很多小时。非常感谢您的帮助!

设置

  • Cocos2d 2.0

问题

  • EXC_BAD_ACCESS当我在CCLabelTTF上设置字符串时
  • 大约每5次尝试中就有1次发生

代码

以下代码来自类LevelSelectionLayer。这个类是另一个类的委托,该类处理级别网格和触摸交互。

在LevelSelectionLayer.h中

@property (strong) NSArray *difficulties;
@property (strong) CCLabelTTF *difficultyLabel;
@property (strong) SlidingMenuGrid *slidingMenuGrid;

在LevelSelectionLayer.m中

-(id) init
{
    if (self = [super init]) {
        self.difficulties = [[NSArray alloc] initWithObjects:@"Easy", @"Intermediate", @"Hard", nil];
        [self initDifficultyLabel];
        [self initGrid];
    }
    return self;
}
-(void) initDifficultyLabel
{
    CGSize size = [[CCDirector sharedDirector] winSize];
    self.difficultyLabel = [[CCLabelTTF alloc] initWithString:[self.difficulties objectAtIndex:0] fontName:FONT_BOLD fontSize:18.0f];
    self.difficultyLabel.position = ccp(size.width / 2 + 3, size.height / 2 + 63);
    self.difficultyLabel.color = CCC3_DARK_COLOR;
    [self addChild:self.difficultyLabel z:5];
}

在LevelSelectionLayer.m中(续)。这是一个从上面提到的网格类中调用的委托方法

-(void) slidingGridDidChangePage
{
    // Get curent page
    int currentPage = self.slidingMenuGrid.iCurrentPage;
    CCLOG(@"currentPage:%d", currentPage); // Always prints correct number
    // Adjust pagination display
    for (int i = 0; i < NUM_PAGES; i++) {
        CCSprite *bub = [self.pageBubbles objectAtIndex:i];
        if (i == currentPage) {
            bub.displayFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"pageSelected.png"];
        }
        else {
            bub.displayFrame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:@"page.png"];            
        }
    }
    // Adjust difficulty labeL
    /******* BREAKS HERE *******/
    self.difficultyLabel.string = (NSString *)[self.difficulties objectAtIndex:currentPage];
    //self.difficultyLabel.string = @"Test"; // Breaks every once in a while as well
}

很可能,困难标签是在应用程序流程的某个地方发布的。由于您在创建它之后立即将其添加到层中(在移除它或释放层之前,它一直保留在层中),因此不需要分配它,也不需要在任何地方释放它。

我遇到了我认为相同的问题。它只发生在设备的发布版本上。当我启用僵尸检测时,在崩溃时,我会收到警报,"setPosition"方法正在对已释放的对象(我的CCLabelTTF)调用,这发生在我创建标签后的下一行。出于某种原因,ARC似乎在创建标签之间发布了标签,但在我向其发送任何消息之前。其他可能有用的信息:我正在将标签分配给用__unsaf_unrained指令声明的ivar,因为我只想保持对标签的"弱"引用,这样我以后就可以修改它,而不必通过标记从它的父层获取它(标签是作为创建它的层的子层添加的,应该会保留它)。当我使用临时变量设置标签时,不会发生这种情况。对我来说同样奇怪的是,所有其他CCNode子类在分配方面的行为完全相同,但我只对CCLabelTTF有这个问题。

EDIT:还值得一提的是,我正在使用CCLabelTTF的一种方便方法(返回一个自动释放的对象)来创建标签,因此理论上,该对象应该在创建它的函数的范围之外保持,直到自动释放池耗尽。

编辑:我已经解决了我的问题。不确定它是否有助于OP,但它是:使用__weak而不是__unsafe_unretained。AFAIK这只适用于支持iOS 5.0+的应用程序,但对我来说没关系,我现在不打算支持任何不支持的东西。

最新更新