【问题标题】:iOS Cocos2d CCLabelTTF Set String Ends in Exc Bad AccessiOS Cocos2d CCLabelTTF Set String Ends in Exc Bad Access
【发布时间】:2012-08-24 21:17:46
【问题描述】:

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

设置

  • ARC
  • 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
}

【问题讨论】:

  • 启用僵尸对象(在 Xcode 编辑目标的构建方案中)以查看崩溃是否是由于释放的对象
  • 我为模拟器和设备都启用了僵尸。但是,在模拟器中根本没有崩溃。对于该设备,输出窗口中没有任何帮助。除此之外,它只是说线程 8 - sgxBindResource 和 EXC_BAD_ACCESS(code=1, address=0x8)

标签: ios cocos2d-iphone nsstring automatic-ref-counting exc-bad-access


【解决方案1】:

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

【讨论】:

  • 我正在使用 ARC,所以我无法真正发布它。而且你不必使用alloc吗?另外,我在设置字符串之前做了一个休息,标签存在并且不是0x0000。它实际上具有属性。有什么想法吗?
  • EXC_BAD_ACCESS 通常意味着内存问题,通常是僵尸。您是否尝试过 Instruments 来监视僵尸并保留计数,正如 LearnCocos2d 已经建议的那样?当这些错误偶尔发生但并非总是发生时,可能是代码的另一部分造成了问题。
  • 我试过了,但模拟器上甚至没有出现错误。它只发生在设备上..
  • 您尝试过在您的设备上运行的仪器吗?无论如何,您都应该尝试一下,因为它更准确,更快
【解决方案2】:

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

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

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

【讨论】:

  • 因此,将标签分配给临时变量,然后 然后 分配给我的 ivar 似乎可以解决问题。这绝对似乎是 ARC 的一个错误,尽管我仍然很困惑为什么它只发生在 CCLabelTTFs
  • 我试试临时变量!感谢您对此的帮助。奇怪的是 ARC 是这样行事的。
猜你喜欢
  • 1970-01-01
  • 2011-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-16
  • 2020-04-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多