Как безопасно удалить объекты из NSMutableSet (cocos2d-iphone) - PullRequest
1 голос
/ 06 августа 2010

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

Я пишу игру с cocos2d-iphone.У меня есть объект сцены с несколькими NSMutableSets в его иварах - юниты, здания, ракеты и т. Д. У меня проблема с удалением объектов из этих NSMutableSets.Когда объект пули запускается, он, среди прочего, ищет цель, которой он должен был бы повредить, вот так:

...
for ( RXUnit * unit in targetSet ) {
    if ( ccpDistance( unit.position, rayPoint ) < 20 ) {
    ... 
    [unit damageSelfBy:damage];
    ...
    }
}
...

Метод [unit damageSelfBy:damage] убивает юнит, если у него недостаточно HP, чтобы выдержать урон,Среди прочего, он делает это:

[scene.units removeObject:self];

(scene.units - это тот же NSMutableSet, что и targetSet в цикле выше)

При использовании этой строки пуля, выпущенная повремя, когда устройство удаляется из набора, не запускается должным образом.Метод bullet init выполняется до цикла for, показанного выше (да, модуль действительно поврежден и удален предыдущим маркером), но все остальное, что идет после этого цикла в методе init, просто не выполняется.

Удивительно, но приложение продолжает нормально работать без видимых эффектов, кроме этой застрявшей пули.Консоль не показывает никаких предупреждений / ошибок, при компиляции также нет предупреждений.

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

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

Любая помощь / идеи очень ценятся.Может быть, мне даже не следует хранить игровые объекты в NSMutableSets?

Ответы [ 2 ]

3 голосов
/ 06 августа 2010

Если вы удалите объект из набора, и этот набор является единственной ссылкой на объект, тогда объект может быть освобожден прямо тогда.Задумайтесь на секунду: объект , методы которого вы используете , может исчезнуть прямо сейчас .Это плохо ™.

Вот почему ваше отложенное удаление работает;это не уловка.Вы ждете, пока не закончите использовать объект, затем вы удаляете его.Однако есть и лучший способ, чем ваш objectsToRemove трюк:

[self retain];
[self autorelease];
[scene.units removeObject:self];

autorelease приведет к тому, что отложенное сообщение release будет отправлено вашему объекту после завершения цикла выполнения, поэтому с помощью retain, затем autorelease, вы предотвращаете исчезновение объекта в секунду, когда он был удален из scene.units.

3 голосов
/ 06 августа 2010

Является ли заданный контейнер единственной ссылкой на объект?Я не уверен, что существует определенное поведение, если вы освобождаете объект во время выполнения его методов.Возможно, вам потребуется пометить его как «мертвый», а затем выполнить очистку.

...