2011-01-25 2 views
1

Вот два фрагмента кода Objective-C в приложении Foundation. Этот кусок кода в функции:-dealloc метод не вызывается, когда владелец массива dealloc'd ... не так ли?

[arrayOfObjects addObject:[[TheShape alloc] init]]; 
    NSLog(@"%@", arrayOfObjects); // log verifies "<TheShape..." is in the array 
    [arrayOfObjects release]; 

и в моем классе TheShape, у меня есть этот метод dealloc переопределения:

- (void)dealloc { 
     NSLog(@"TheShape dealloc called."); 
     [super dealloc]; 
    } 

Хотя моя программа работает иначе, он не работает так, как я ожидайте этого. Когда отправляется сообщение [arrayOfObjects release], я ожидаю увидеть строку «TheShape dealloc ...» в журнале. Это не так.

Q1: Почему бы и нет?

Так что я копаю немного и упрощаю вещи. Если я сделаю что-то более простое:

TheShape *aShape = [[TheShape alloc] init]; 
    [aShape release]; 

Отладочное сообщение по-прежнему не отображается в журнале.

Q2: Почему бы и нет?

Но если я это сделать:

TheShape *aShape = [TheShape new]; 
    [aShape release]; 

сообщение отладки делает появится в журнале. Отладочное сообщение также появляется в журнале, если я изменил значение alloc/init в первом примере на new.

Q3: Почему?

Очевидно, что в цикле alloc/init/release (Q's 1 и 2) отсутствует явная концептуальная схема и в предполагаемой эквивалентности new и alloc/init (Q3). Может ли кто-нибудь указать мне на учебник, который объясняет вещи немного больше для трудномысленного мышления, как я?

Спасибо,

Билл

+0

Не должно быть разницы между 'TheShape * aShape = [[TheShape alloc] init];' и 'TheShape * aShape = [TheShape new];'. – Mahesh

ответ

5

если случайно вы преимущественную +new на вашем классе? Он должен делать то же самое, что и +alloc/-init.

В любом случае, ваша самая первая строка

[arrayOfObjects addObject:[[TheShape alloc] init]]; 

протекает ваш TheShape экземпляр. Вы должны включить что и

[arrayOfObjects addObject:[[[TheShape alloc] init] autorelease]]; 
+0

Я не переопределял новый класс, но я мог видеть, где это было бы проблемой, если бы у меня было. Я ожидал, что новый будет действовать точно так же, как alloc/init, но это не по какой-то нечетной причине. Я все еще думаю об этом.
Создание авторекламы TheShape делает трюк. Что происходит в первом случае? Да, я выделяю/init, поэтому владею этим объектом, но не нужно ли массировать объекты, чтобы отслеживать его для меня? Это один из тех случаев, когда я четко думаю, что одна вещь должна произойти, и кардинал Рулез Objective-C Memory Management, похоже, не согласен. Уточнение будет оценено по достоинству. – BillEccles

+0

Массив не «захватывает» ваше владение объектом. Это добавляет свою собственность. Объект может принадлежать нескольким другим объектам. В этом случае массив принадлежал ему, но также и ваш локальный метод. Вам нужно отказаться от участия в нем после того, как массив подберет его. –

+0

Ах, zneak (ниже) ответил, что для меня. (Платит читать дальше, я думаю.) – BillEccles

1

Там нет причин для метода dealloc будет называться: Ваш объект до сих пор имеет счетчик ссылок ненулевых.

Всякий раз, когда вы создаете объект, он начинает свое существование с подсчета ссылок 1. Когда это число достигает 0, оно освобождается. Существуют определенные правила управления памятью, которые помогают нам оставаться в здравом уме. Эти правила говорят о «собственности объекта».

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

  • Вы называете retain на объекте;
  • Вы получаете объект по телефону copy или mutableCopy на другом;
  • Вы вызываете метод alloc на объекте.

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

В вашем фрагменте вы создали объект, который вы передаете в свой массив. Ваш массив начинает использовать его, поэтому он называет его retain (поэтому он остается живым, пока он держится). Однако, как только вы окажетесь release, ваш объект все равно должен быть освобожден вы, так как вы вызвали метод alloc.


EDIT Простой фрагмент:

TheShape *aShape = [[TheShape alloc] init]; 
[aShape release]; 

должен показать сообщение, хотя. :/

Есть две причины, я могу видеть, что это не происходит:

  • Вы сделали что-то странное или с alloc, init или release метода (в этом случае, разместить свой код);
  • Вы запускаете среду сбора мусора, и dealloc просто не будет называться (это finalize вы должны использовать в этом случае). Хотя я не понимаю, почему +new тогда release дал бы ожидаемые результаты.
+0

'-init' не подразумевает право собственности. С другой стороны, методы, имена которых содержат 'alloc' или' new' do. –

+0

@Bavarious Woops, вы правы. – zneak

+0

Хотя я понимаю, что говорит Баварий (CAN = право собственности), я не уверен, что он ссылается в вашем оригинальном посте, что вы ... о, неважно. Я просто щелкнул ссылку на ревизии. Понял. Спасибо, парни! – BillEccles

1

Этот Link содержит полезную информацию об управлении памятью.