установка объектов на ноль при выпуске NSArray

Когда я получаю предупреждение о памяти, я выпускаю кучу объектов, хранящихся в NSMutableArray.

[_children release];

Мне также нужно в какой-то момент выполнить рекурсию по объектам (возможно, после того, как произошло предупреждение памяти), поэтому мне нужно проверить, существуют ли еще объекты, что я и делаю со сравнением с nil, что не сработает, потому что освобождение массив ничего не обнуляет.

Я не могу перебирать массив, удаляя объекты 1 на 1 и устанавливая значение nil, потому что мне не разрешено изменять массив во время итерации.

Такое ощущение, что я упускаю что-то очевидное. Я просто хочу освободить + nil некоторые значения в массиве.


person Sam    schedule 18.08.2009    source источник


Ответы (2)


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

NSObject * a = [[NSObject alloc] init];
NSObject * b = a;

[a release];
a = nil;

// b is NOT nil! b still points to the memory location where
// a used to be, which is now not valid anymore and using b
// for anything may crash your application!

Если я помещу «а» в массив, а затем снова удалю его из массива, счетчик сохранения «а» уменьшится на единицу. Либо он все еще больше нуля, и в этом случае «а» не будет освобожден, либо он равен нулю, и в этом случае он будет освобожден. Установка ссылки на a в nil после того, как она была освобождена, не влияет на другие переменные, все еще указывающие на «a».

Таким образом, даже если NSArray устанавливал ссылку на «a» в nil после удаления ее в массив и освобождения (поскольку его счетчик ссылок стал равным нулю), это не повлияет на переменную экземпляра, все еще указывающую на «a».

Я не совсем уверен, что вы пытаетесь сделать, и это, безусловно, возможно, но вы на совершенно неправильном пути.

person Mecki    schedule 18.08.2009
comment
Спасибо за разъяснения. Я был на неверном пути и нашел обходной путь. Я работаю на C++, так что это было не сразу очевидно. В вашем примере я бы предположил, что b == nil - person Sam; 18.08.2009
comment
Поскольку я не знаю, что вы на самом деле делаете, я не мог предложить лучшего решения. Если объекты в массиве являются вашими собственными классами, вы, конечно, можете переопределить метод Dealloc (который вызывается, когда сохраненное количество достигает нуля) и уведомить другие объекты (например, делегаты или просто широковещательное уведомление), что вы сейчас умрете, поэтому все другие объекты могут обновить свои ссылки на вас до нуля. - person Mecki; 18.08.2009
comment
Даже в C++, если у вас есть указатель на объект, адрес, который вы держите, не будет очищен, когда сам объект будет уничтожен — у вас будет недопустимый указатель, точно так же, как в Objective-C, когда счетчик сохранения упадет до 0, и вы все еще есть ссылка, указывающая, где память была выделена... - person Kendall Helmstetter Gelner; 18.08.2009

Предполагая, что вы не сохраняете элементы массива в другом месте, безусловно, удаляя объект из массива или освобождая сам массив, вы также освобождаете элемент (ы). Думаю, это все, что вам нужно сделать.

Из документации Apple:

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

person teabot    schedule 18.08.2009
comment
Но как я узнаю, что он выпущен? Я не могу запросить его, так как он не существует, и он оставляет меня с оборванным указателем... - person Sam; 18.08.2009
comment
Потому что так говорит Apple API. В нем говорится, что если вы удалите объект из массива или освободите массив, объект массива БУДЕТ освобожден. - person teabot; 18.08.2009
comment
Вы неправильно поняли - я не могу сделать if (appleAPISaysThisObjectIsReleasedOrNot()) во время выполнения. Я нашел обходной путь, так что все равно спасибо. - person Sam; 18.08.2009