Свойство NSMutableArray — выпуск дочерних элементов

#iphone #objective-c #ios

#iPhone #objective-c #iOS

Вопрос:

Вот что я вижу, когда запускаю следующий код:

 // Dealloc on MyClass not called
MyClass* c = [MyClass new];
self.a = [NSMutableArray new];
[self.a addObject:c];
[c release];
[a release];

// Dealloc on MyClass called
MyClass* c2 = [MyClass new];
NSMutableArray* a2 = [NSMutableArray new];
[a2 addObject:c2];
[c2 release];
[a2 release];

// Dealloc on MyClass called
MyClass* c3 = [MyClass new];
a = [NSMutableArray new];
[a addObject:c3];
[c3 release];
[a release];
  

Почему в первом примере не вызывается dealloc?

Редактировать:

Я думаю, что я все это неправильно понял. В основном, что мне нужно сделать, это:

 NSMutableArray* alocal = [NSMutableArray new]; // alocal has a retain count of 1
self.a = alocal; // a has a retain count of 1
[alocal release]; // alocal has a retain count of 0
[a release]; // a has a retain count of 0
  

или

 self.a = [[NSMutableArray new] autorelease]; // a has a retain count of 2
[a release]; // a has a retain count of 0
  

или

 self.a = [NSMutableArray array]; // a has a retain count of 2
[a release]; // a has a retain count of 0
  

Просто в качестве примечания, с параметрами автоматического выпуска / массива (# 2 и # 3) a не освобождается сразу, поэтому, если вы хотите больше контроля, выберите вариант # 1.

Спасибо!

Комментарии:

1. Интересно… Итак, по сути, вы хотите, чтобы оно было освобождено прямо в этот момент, да? Ну, звучит справедливо. Обычно мы просто позволяем пулу автоматически освобождаться самостоятельно, но вы правы, он не будет выпущен сразу.

Ответ №1:

Поскольку в первом примере предполагается a , что это свойство сохранения / копирования, массив протекает.

 self.a = [NSMutableArray new];
  

что, кстати, отличается от третьего примера:

 a = [NSMutableArray new];
  

В третьем случае объект присваивается непосредственно ivar (без участия установщика свойств).

Возвращаясь к первому примеру, метод new возвращает сохраненный объект ( 1), а затем установщик свойств также сохраняет объект ( 2). Затем, когда свойство освобождается (-1), вы получаете 1. Это неправильно. Вам необходимо сбалансировать сохранение / выпуски, чтобы в итоге получить 0.

Простым решением является использование удобного конструктора:

 self.a = [NSMutableArray array];
  

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


Кроме того, в первом примере вы освобождаете объект, который вы присвоили свойству, через ivar:

 [a release];
  

В результате свойство теперь содержит указатель на потенциально освобожденный объект. Поскольку вы отказались от права собственности на объект, нет никакой гарантии, что объект будет активен в будущем. Если объект был фактически освобожден (поскольку у него нет других владельцев), ваш указатель все равно будет указывать на адрес памяти в куче, где раньше находился объект; за исключением того, что теперь этот адрес может содержать что угодно: старый битовый шаблон указанного объекта или несвязанный объектили абсолютный мусор.

Ничего хорошего не произойдет, если вы отправите сообщение освобожденному объекту, например, это приведет к сбою вашего приложения. Чтобы избежать этого, освободите объект через свойство:

 self.a = nil;
  

Комментарии:

1. Когда я делаю …self.a = [Массив NSMutableArray]; освобождение по-прежнему не вызывается. Также, когда я вызываю …self.a = [[NSMutableArray new] авторелиз]; освобождение по-прежнему не вызывается.

2. @user472292 Теперь, когда массив больше не протекает, он должен быть вызван. Должно быть, происходит что-то еще. Можете ли вы предоставить более подробную информацию?

3. Я уверен, что массив не протекал. Прежде чем я вызвал [релиз] Я проверил количество сохранений, и оно равнялось 1.

4. @user472292 как объявляется свойство a ? Свойства задаются assign по умолчанию, поэтому, если вы ничего не указываете, они есть assign , что обычно используется для примитивных типов и объектов, которыми вы не владеете, как делегаты. В этом случае это должно быть retain или copy , что является первым предположением моего поста. Итак, как оно a объявлено?

5. @свойство (неатомное, сохранить) NSMutableArray* a;

Ответ №2:

Это зависит от того, как вы реализовали свойство ‘a’, которым оно должно быть:

 @property (retain) NSMutableArray *a;
  

также при использовании ‘new’ он помещает выделение, поэтому вы должны автоматически освободить его следующим образом:

 self.a = [[NSMutableArray new] autorelease];
  

Комментарии:

1. Когда я делаю …self.a = [Массив NSMutableArray]; освобождение по-прежнему не вызывается. Также, когда я вызываю …self.a = [[NSMutableArray new] авторелиз]; освобождение по-прежнему не вызывается.