Удаление объекта из NSMutableArray после обновления до SDK 5 для iOS приводит к сбою приложения - PullRequest
0 голосов
/ 28 ноября 2011

[Редактировать] Я изменил порядок удаления obj из списка.Первоначально, как это все еще вызывало ту же ошибку.

Это код, о котором идет речь.Я считаю, что ошибка сузилась до строки, где она удаляет объект из _blocks NSMutableArray.У меня точно такой же код в других частях моего кода, удаление аналогичного объекта из того же массива.По какой-то причине при вызове этой функции происходит сбой игры.У меня не было этой проблемы до того, как я обновился до последней версии XCode, которая поддерживает iOS SDK 5 и armv7.До того, как я обновил XCode, он работал нормально.Я бы вошел в предмет, и предмет исчез бы с экрана.Теперь он просто падает, когда я получаю предмет.Любая помощь будет принята с благодарностью.

-(void)itemCollision:(Collidable *)obj :(int)itemID :(int)objID: (bool)withPlayer{
[background removeChild:[obj getSprite] cleanup:YES];
[background removeChild:[obj getArrow] cleanup:YES];
[_blocks removeObject:obj];
//[obj release];
if(withPlayer){
    if(itemID == 1){
        [[SimpleAudioEngine sharedEngine] playEffect:@"Item2.mp3" pitch:1.0f pan:0.0f gain:0.3f];
        points += (10 + level * 22);
    }
}

}

#import <UIKit/UIKit.h>

int main(int argc, char *argv[]) {

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, @"AppDelegate");
[pool release];
return retVal;

}

При сбое приложения оно выделяет следующую строку:

int retVal = UIApplicationMain(argc, argv, nil, @"AppDelegate");

Сообщение об ошибке: «Поток 1: Программа получила сигнал:« SIGARBRT ».

Вот код, по которому я вызываю itemCollision:

-(bool) isCollision {
CCSprite *playerSprite = mob;//[mob getSprite];

CGRect playerRect = CGRectMake(playerSprite.position.x - (playerSprite.contentSize.width/2), 
                               playerSprite.position.y - (playerSprite.contentSize.height/2), 
                               playerSprite.contentSize.width, 
                               playerSprite.contentSize.height);

//Player Collision

BOOL collision = FALSE;

for (Block *block in _blocks) {
    CCSprite *blockSprite = [block getSprite];
    CGRect blockRect = CGRectMake(blockSprite.position.x - (blockSprite.contentSize.width/2), 
                                  blockSprite.position.y - (blockSprite.contentSize.height/2), 
                                  blockSprite.contentSize.width, 
                                  blockSprite.contentSize.height + 1 + [mob getSpeed]);
    if (CGRectIntersectsRect(blockRect, playerRect)) {
        if ([block getItemID] != 0) {
            [self itemCollision:block :[block getItemID] :[block getID] :TRUE];
            continue;
        }
        if(playerSprite.position.y > blockSprite.position.y){
            collision = TRUE;
        }
        if(collision) {
            [[SimpleAudioEngine sharedEngine] playEffect:@"squish.caf"];
            [self die];
            return TRUE;
        }
    }
}   
return FALSE;

}

ЗдесьВот как я удаляю объекты из _блоков в других местах кода. Это происходит в функции таймера гравитации:

NSMutableArray *blocksToDelete = [[NSMutableArray alloc] init];

for (Block *block in _blocks) {
    CCSprite *blockSprite = [block getSprite];
    //[block addSpeed:gravity];
    [block setPreX:blockSprite.position.x];
    [block setPreY:blockSprite.position.y];
    blockSprite.position = ccp(blockSprite.position.x, blockSprite.position.y - [block getSpeed]);
    if (blockSprite.position.y < -30 + blockSprite.contentSize.height / 2) {
        [blocksToDelete addObject:block];
    }
    if(blockSprite.position.y - blockSprite.contentSize.height < [block getArrow].position.y){
        [block getArrow].visible = FALSE;
    }
}

for (Block *b in blocksToDelete) {
    [_blocks removeObject:b];
    [background removeChild:[b getSprite] cleanup:YES];
    [background removeChild:[b getArrow] cleanup:YES];
    [b release];
}

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

Ответы [ 2 ]

2 голосов
/ 28 ноября 2011

Если массив имел последнее сохранение на объекте, он будет освобожден, когда вы удалите его. Вы продолжаете использовать объект для остальной части метода, поэтому он должен остаться в живых. Конечно, проверка retainCount объекта obj для определения того, имеет ли NSMutableArray последнее сохранение, является первым местом для запуска.

Если мы пока предположим, что это так, то попробуйте этот альтернативный подход:

-(void)itemCollision:(Collidable *)obj :(int)itemID :(int)objID: (bool)withPlayer
{
    [[obj retain] autorelease];
    [_blocks removeObject:obj];
    [background removeChild:[obj getSprite] cleanup:YES];
    [background removeChild:[obj getArrow] cleanup:YES];
    if(withPlayer){
        if(itemID == 1){
            [[SimpleAudioEngine sharedEngine] playEffect:@"Item2.mp3" pitch:1.0f pan:0.0f gain:0.3f];
            points += (10 + level * 22);
        }
    }
}

Когда отладчик переходит на main.m, это часто происходит из-за того, что он умирает при извлечении пула автоматического выпуска - задача, для которой у вас нет символов отладки, поэтому он переходит к самому глубокому фрейму стека, для которого у него есть источник для показа. вы, который в случае пулов с автоматическим выпуском в главном потоке, будете выполнять функцию main ().

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

0 голосов
/ 28 ноября 2011

Трудно точно знать, что происходит за рамками примера кода, которым вы поделились, но можно предположить, что ваш obj переиздан. Он освобождается один раз, когда вы удаляете его из массива, а затем вы выпускаете его снова. Это может или не может быть уместным, учитывая количество сохраненных объектов для этого объекта.

Чтобы начать устранение неполадок, попробуйте использовать инструмент Instrument Zombie - это поможет вам увидеть, действительно ли оно переиздано.

Вы можете дополнительно закомментировать ваш:

[obj release]

Чтобы увидеть, останавливает ли это ошибку (которая может быть, а может и не быть решением, но должна быть проницательной в любом случае).

...