Поток 1: EXEC_BAD_ACCESS (код =1), адрес =0x6000000000000018)
Прочитайте все сообщения, касающиеся этой ошибки, связанной с памятью и попыткой получить доступ к тому, чего больше нет.
Проблема: ошибка появляется практически случайно. Это может появиться после того, как первый враг убит или N-й враг убит. Тем не менее, он появляется только тогда, когда враг убит.
Тестирование: запуск iOS 8 beta 5, Xcode 6 beta 5 на iPhone 5s.
Поток кода:
Экземпляры класса Enemy SKNodes создаются в начале уровня и сохраняются в NSMutableArray для справки:
Goblin *newGoblin = [[Goblin alloc] initFacingDirection:1];
// set various properties…
[enemyGoblins addObject:newGoblin];
Меч игрока вступает в контакт с врагом:
NSMutableArray *discardedItems = [NSMutableArray array];
for(Goblin *object in enemyGoblins)
{
[object runBloodBurst:true damagePoints:_player.swordDamage];
if(object.goblinHealth < 0)
[discardedItems addObject:object];
}
if([discardedItems count] > 0)
[enemyGoblins removeObjectsInArray:discardedItems];
В классе гоблинов код "die":
if(self.goblinHealth < 0)
{
SKAction *wait0 = [SKAction waitForDuration:1.0];
SKAction *block0 = [SKAction runBlock:^{
[self removeActionForKey:@"animation"];
[self runAction:[_animations goblin_dieLeft]];
}];
SKAction *block1 = [SKAction runBlock:^{
[self removeFromParent];
}];
[self runAction:[SKAction sequence:@[block0, wait0, block1]]];
}
Что я пробовал: я отключил код discardedItems, потому что думал, что ARC может сбросить объект из памяти после потери ссылки, а последующий класс "Goblin" "die animation" вызовет сбой, но это не решит проблему. Я пробовал зомби и контрольные точки, но также не получил никаких полезных подсказок.
Я лаю не на том дереве в отношении того, что я пробовал, или кто-то сталкивался с подобной проблемой в бета-версии 5?
РЕДАКТИРОВАТЬ
Вот обратный след:
(lldb) bt * thread # 1: tid = 0x3264b, 0x000000018cb13434 SpriteKit
SKCSprite::update(double) + 404, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x7000000000000018) frame #0: 0x000000018cb13434 SpriteKit
SKCSprite:: update (double) + 404 кадр №1: 0x000000018cb13440 SpriteKitSKCSprite::update(double) + 416 frame #2: 0x000000018cb13440 SpriteKit
SKCSprite:: update (double) + 416 кадр # 3: 0x000000018cacbf28 SpriteKit-[SKScene _update:] + 140 frame #4: 0x000000018cae63f8 SpriteKit
- [SKView (Private) _update:] + 568 кадр # 5: 0x000000018cae3a10 SpriteKit-[SKView renderCallback:] + 764 frame #6: 0x000000018cae0a9c SpriteKit
__29- [SKView setUpRenderCallback] _block_invoke + 60 кадров # 7: 0x000000018cb0d890 SpriteKit-[SKDisplayLink _callbackForNextFrame:] + 272 frame #8: 0x000000010042ca9c libglInterpose.dylib
- [DYDisplayLinkInterposer forwardDisplayLinkCallback:] + 168 кадров № 9: 0x000000018c615b90 QuartzCoreCA::Display::DisplayLinkItem::dispatch() + 32 frame #10: 0x000000018c615a28 QuartzCore
CA:: Display:: DisplayLink:: dispatch_items (длинная без знака, длинная без знака, длинная без знака) + 324 кадра # 11: 0x00000001897dddc0 IOKitIODispatchCalloutFromCFMessage + 376 frame #12: 0x00000001885dcf34 CoreFoundation
__CFMachPortPerform + 180 frame # 13: 0x00000001885f1b38 CoreFoundation__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 56 frame #14: 0x00000001885f1a98 CoreFoundation
__CFRunLoopDoSource1 + 436 кадр № 15: 0x00000001885efa18 CoreFoundation__CFRunLoopRun + 1640 frame #16: 0x000000018851d664 CoreFoundation
CFRunLoopRunSpecific + 396 кадра # 17: 0x000000019154f5a4 GraphicsServicesGSEventRunModal + 168 frame #18: 0x000000018ccd6164 UIKit
UIApplicationMain + 1488 * frame # 19: 0x0000000100165530 CarcerQuestmain(argc=1, argv=0x000000016fdab9d8) + 116 at main.m:16 frame #20: 0x000000019885aa08 libdyld.dylib
начало + 4 (лдб)
3 ответа
Менять
[self runAction:[SKAction sequence:@[block0, wait0, block1]]];
в
[self runAction:[SKAction sequence:@[block0, wait0]] completion:^{
[_self removeFromParent];
}];
Я столкнулся с той же проблемой при обновлении кода IOS7 для запуска на IOS8, и с помощью блока завершения исправил проблему.
Прочитав комментарии к вашему вопросу, я не уверен, что вы решили эту проблему, и ваш фрагмент кода недостаточно полон, чтобы я смог увидеть вашу проблему, но недавно я столкнулся с подобной проблемой, и мне потребовалось пока не пойму, так что я бы опубликовал это на тот случай, если это пригодится вам или будущему читателю поста.
Вы можете увидеть мой код изменения здесь: https://github.com/ik/2048/commit/3ffec547367320c7e179624a14ac5867ed1acea2
В основном, что происходит, runAction
асинхронный Это выполняется в следующем цикле обновления экрана (отсюда вызов ссылки на отображение в вашей трассировке стека). Так что если вы позвоните removeSomething
после вашего runAction
, это может быть выполнено до того, как действие будет выполнено, и вы потерпите крах.
По крайней мере, это то, что поймало меня - я не знаю, почему это никогда не происходило в iOS 7. См. Код ниже.
- [self removeFromParentCell]; // Used to call it here - wrong.
SKAction *wait = [SKAction waitForDuration:GSTATE.animationDuration];
SKAction *remove = [SKAction removeFromParent];
- [self runAction:[SKAction sequence:@[wait, remove]]];
+ [self runAction:[SKAction sequence:@[wait, remove]] completion:^{
+ [self removeFromParentCell]; // This is right.
+ }];
Поискив форумы поддержки Apple и запустив тот же проект на iOS 7, выясняется, что это ошибка бета-версии, а не неисправный код.