Коллекция причины NSGenericException <NSConcreteMapTable: xxx>

Это ошибка, которую я вижу, когда присутствует SKSceneэта ошибка возникает случайно и не может быть воспроизведена

* Завершение работы приложения из-за неисследованного исключения "NSGenericException", причина: "* Коллекция была видоизменена при перечислении".

что случилось?

скажите мне, если вам нужна другая информация

Спасибо

РЕДАКТИРОВАТЬ:

*** First throw call stack:
(
    0   CoreFoundation                      0x025601e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x022298e5 objc_exception_throw + 44
    2   CoreFoundation                      0x025efcf5 __NSFastEnumerationMutationHandler + 165
    3   Foundation                          0x01e47f03 -[NSConcreteMapTable countByEnumeratingWithState:objects:count:] + 66
    4   CoreFoundation                      0x0253d77f -[__NSFastEnumerationEnumerator nextObject] + 143
    5   SpriteKit                           0x01d009f2 +[SKTextureAtlas(Internal) findTextureNamed:] + 232
    6   SpriteKit                           0x01cf709c __26-[SKTexture loadImageData]_block_invoke + 1982
    7   SpriteKit                           0x01d34d09 _Z14SKSpinLockSyncPiU13block_pointerFvvE + 40
    8   SpriteKit                           0x01cf6898 -[SKTexture loadImageData] + 228
    9   SpriteKit                           0x01cf65d9 __51+[SKTexture preloadTextures:withCompletionHandler:]_block_invoke + 241
    10  libdispatch.dylib                   0x02b117b8 _dispatch_call_block_and_release + 15
    11  libdispatch.dylib                   0x02b264d0 _dispatch_client_callout + 14
    12  libdispatch.dylib                   0x02b14eb7 _dispatch_root_queue_drain + 291
    13  libdispatch.dylib                   0x02b15127 _dispatch_worker_thread2 + 39
    14  libsystem_c.dylib                   0x02de1e72 _pthread_wqthread + 441
    15  libsystem_c.dylib                   0x02dc9daa start_wqthread + 30
)
libc++abi.dylib: terminating with uncaught exception of type NSException

4 ответа

Иногда я получаю такое же исключение. Это было вокруг некоторое время, и я пытался определить это в течение нескольких недель.

Я подозреваю, что это может произойти из-за предварительной загрузки текстур, либо вручную, либо автоматически запускаемой Sprite Kit, в то время как другой код вызывает загрузку или доступ к текстурам.

Я сократил свои preloadTextures: звонки до одного, но я все еще получаю проблему, только реже. Я пытался выполнить Selector: onMainThread: всякий раз, когда я запускаю селектор, который получает доступ или загружает изображения (или просто может внутренне) изнутри CompleteBlock или другого кода, который выполняется в другом потоке.

У меня не было этого сбоя весь день сегодня после того, как я переместил свой код пользовательского интерфейса в основной поток (он вызывался из обработчика завершения). Я не могу сказать на 100% наверняка, исправило ли это все же.

Надеюсь, это немного поможет. Там определенно что-то привередливое происходит, и если вы делаете po 0x1459da60 (в окне команд lldb, используя адрес, указанный в исключении), вы увидите, что это текстовый список SKTextureAtlas, который изменяется. Я надеюсь, что это поможет вам точно определить, откуда возникла проблема с вашей стороны.

Из того, что я могу сказать это ошибка набора спрайтов в методе набора спрайтов:

preloadTextures: withCompletionHandler:

Единственный способ, которым я смог это исправить, это полное удаление этого метода. Согласно документам Apple, текстуры также загружаются, если вы получаете доступ к size имущество. Так что мой обходной путь - сделать именно это:

for (SKTexture *texture in self.texturesArray) {
    texture.size;
}

Это не красиво, но это работает!

У меня была такая же проблема, когда я пытался предварительно загрузить две простые анимации. Я попытался предварительно загрузить анимацию в словарь и подготовить ее к вызову через строковый ключ. Вот что я пробовал

-(void)setupAnimDict {
    animDict = [[NSMutableDictionary alloc] init];

    [animDict setObject:[self animForName:@"blaze" frames:4] forKey:@"blaze"];
    [animDict setObject:[self animForName:@"flame" frames:4] forKey:@"flame"];
}

-(SKAction *)animForName:(NSString *)name frames:(int)frames {
    NSArray *animationFrames = [self setupAnimationFrames:name base:name num:frames];
    SKAction *animationAction = [SKAction animateWithTextures:animationFrames     timePerFrame:0.10 resize:YES restore:NO];
    return [SKAction repeatActionForever:animationAction];
}

-(NSArray *)setupAnimationFrames:(NSString *)atlasName base:(NSString *)baseFileName num:(int)numberOfFrames {

    [self preload:baseFileName num:numberOfFrames];

    NSMutableArray *frames = [NSMutableArray arrayWithCapacity:numberOfFrames];
    SKTextureAtlas *atlas = [SKTextureAtlas atlasNamed:atlasName];
    for (int i = 0; i < numberOfFrames; i++) {
        NSString *fileName = [NSString stringWithFormat:@"%@%01d.png", baseFileName, i];
        [frames addObject:[atlas textureNamed:fileName]];
    }

    return frames;
}

-(void)preload:(NSString *)baseFileName num:(int)numberOfFrames {

    NSMutableArray *frames = [NSMutableArray arrayWithCapacity:numberOfFrames];

    for (int i = 0; i < numberOfFrames; i++) {
        NSString *fileName = [NSString stringWithFormat:@"%@%01d.png", baseFileName, i];
        [frames addObject:[SKTexture textureWithImageNamed:fileName]];
    }

    [SKTexture preloadTextures:frames withCompletionHandler:^(void){}];
}

Когда я вызывал метод setupDict, я иногда получал ту же ошибку, что и вы. Проблема состояла в том, что предварительная загрузка двух моих анимаций сталкивалась друг с другом. Я избавился от ошибки, изменив

[SKTexture preloadTextures:frames withCompletionHandler:^(void){}];

в

if ([baseFileName isEqualToString:@"blaze"]) {
        [SKTexture preloadTextures:frames withCompletionHandler:^{
            [self setupFlame];
        }];
    } else {
        [SKTexture preloadTextures:frames withCompletionHandler:^(void){}];
    }

так что первая предварительная загрузка была сделана до того, как я попытался предварительно загрузить другую.

Я не знаю, если это ваша проблема, но если это так, дайте нам знать.

То же самое по-прежнему происходит для меня в Xcode 6.3 beta / Swift 1.2. Вот временное исправление, которое сработало для меня.

SKTextureAtlas.preloadTextureAtlases([SKTextureAtlas(named: "testAtlas")], withCompletionHandler: {
    dispatch_async(dispatch_get_main_queue(), {
        handler()
    })
})

Я фактически обернул это в функцию, чтобы все предварительные загрузки проходили через нее. Таким образом, если это исправлено на стороне SpriteKit, или если при таком подходе есть серьезные недостатки, я могу удалить диспетчеризацию.

Другие вопросы по тегам