iPhone cocos2d спрайты в массиве, проблемы с памятью

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

Я использую следующий код:

Sprite * Trees[50];
Layer * Forest;

Forest =  [Layer node];
Forest.isTouchEnabled = YES;
[self addChild:Forest z:30];

// do this a bunch of times
Trees[0] = [[Sprite spriteWithFile:@"mytree.png"] retain];
[Trees[0] setPosition:cpv(240,160)];
[Forest addChild:Trees[0] z:5];

И затем, когда я хочу уничтожить дерево, я использую:

[Forest removeChild:Trees[0] cleanup:YES];
[Trees[0] release];

Моя проблема в том, что когда я смотрю в «Инструменты», я никогда не восстанавливаю эту память, никогда не возвращаюсь назад. Я думал, что, выпустив спрайт, он освободит память. Я делаю это совершенно неправильно?


person Patrick    schedule 21.03.2009    source источник


Ответы (3)


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

Существует хорошее обсуждение здесь про cocos2d и память.

Я заметил, что все, что вы создаете и сохраняете, должно быть освобождено, но оно не будет освобождено из памяти, пока я не сделаю следующее:

[[TextureMgr sharedTextureMgr] removeAllTextures]; 

Это освободит память.

Вот более крупный пример:

Sprite * sPopup = [[Sprite spriteWithFile:@"popup.png"] retain];
    sPopup.position = cpv(240,440);
    [self addChild: sPopup z:2];
[sPopup release];

Затем, когда я закончу работу с sPopup в другой функции, у меня будет следующее:

[[TextureMgr sharedTextureMgr] removeAllTextures]; 

и память освобождается.

person Bryan Cimo    schedule 14.05.2009

Я подозреваю, что вы «за» сохраняете:

Trees[0] = [[Sprite spriteWithFile:@"mytree.png"] retain];

Если Trees является локальной переменной в функции, вам не нужно сохранять ее в том случае, если spriteWithFile возвращает Sprite с автоматическим освобождением.

Раздел об отложенном выпуске в документация Apple обсуждает это подробнее. Суть в том, что получатель авторелиза гарантированно будет иметь объект, действительный в течение всего срока его действия. Если вам нужен объект, выходящий за рамки функции (например, деревья — это свойство класса), то да, в этом случае вам нужно сохранить (или просто синтезировать свойство, настроенное для сохранения).

Выдавая дополнительное сохранение, вполне вероятно, что ваш счетчик сохранений всегда слишком высок (никогда не достигает 0), и, следовательно, ваш объект не удаляется сборщиком мусора.

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

person hyuan    schedule 21.03.2009
comment
Я считаю, что ваш ответ может быть неправильным. В приведенном выше коде есть два сохранения и два соответствующих выпуска. Ошибка не в коде Патрика. - person EightyEight; 15.05.2009
comment
Я думаю, это зависит от того, как работает spriteWithFile. По соглашению большинство статических методов, которые являются фабриками, возвращаются через автовыпуск (по крайней мере, все API Apple делают это). Если spriteWithFile возвращает Sprite с вызванным для него autorelease, ему не нужно сохранять. Я считаю, что в его коде счетчик сохранения всегда > 0, поэтому память не освобождается. - person hyuan; 17.05.2009
comment
счетчик сохранения/освобождения правильный, однако я бы посоветовал использовать NSMutableArray, чтобы вам не требовалось дополнительное сохранение. - person LearnCocos2D; 23.05.2010

Несмотря на то, что вы вызываете [Tree[x] release], я считаю, что вам все равно нужно «удалить» элемент из массива, например, Trees[x] = nil или что-то в этом роде, поскольку сам массив все еще содержит объект.

«Сохранение» при создании спрайта также не требуется, так как [Forest addChild:z:] также поместит на него сохранение (на самом деле).

person David Higgins    schedule 11.04.2009
comment
Дерево представляет собой массив и, следовательно, не сохраняет хранящиеся в нем объекты... поэтому нет необходимости удалять его из массива для освобождения памяти. - person EightyEight; 15.05.2009
comment
Да, именно поэтому в таких случаях я бы использовал NS(Mutable)Array. - person LearnCocos2D; 23.05.2010