1

在 iPhone 游戏的开发过程中,这花费了我很多时间。任何帮助是极大的赞赏!

设置

  • Cocos2d 2.0

问题

  • 当我在 CCLabelTTF 上设置字符串时出现 EXC_BAD_ACCESS
  • 每 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
}
4

2 回答 2

0

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

于 2012-08-25T19:48:54.483 回答
0

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

编辑:还值得一提的是,我正在使用 CCLabelTTF 的一种便捷方法(它返回一个自动释放的对象)来创建标签,所以理论上该对象应该在它创建的函数范围之外持续存在,直到自动释放池被排干。

编辑:我已经解决了我的问题。不确定它是否会帮助 OP,但它是:使用 __weak 而不是 __unsafe_unretained。AFAIK 这仅适用于支持 iOS 5.0+ 的应用程序,但对我来说这很好,我不打算在这一点上支持任何更少的东西。

于 2012-08-30T17:52:20.520 回答