Стратегия какао для управления указателем / памятью - PullRequest
4 голосов
/ 22 февраля 2009

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

   EditingViewController *controller = [[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];
    self.editingViewController = controller;
    [controller release];

Есть ли какая-либо причина, в частности, что вышеуказанный подход оказывается более выгодным, чем:

self.editingViewController = [[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];

Попытка понять, существует ли стратегия для вышеперечисленного.

Спасибо!

Ответы [ 2 ]

8 голосов
/ 22 февраля 2009

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

По соглашению в Какао и касании Какао любой объект, созданный с использованием [[SomeClass alloc] initX] или [SomeClass newX], создается с сохранением количества единиц. Вы отвечаете за вызов [someClassInstance release], когда закончите работу с новым экземпляром, как правило, с помощью метода dealloc.

Сложность возникает, когда вы назначаете свой новый объект свойству вместо переменной экземпляра. Большинство свойств определены как retain или copy, что означает, что они либо увеличивают счетчик сохранения объекта при его установке, либо делают копию объекта, оставляя оригинал нетронутым.

В вашем примере это, вероятно, есть в вашем файле .h:

@property (retain) EditingViewController *editingViewController;

Итак, в вашем первом примере:

EditingViewController *controller = 
    [[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];
// (1) new object created with retain count of 1

self.editingViewController = controller;
// (2) equivalent to [self setEditingViewController: controller];
// increments retain count to 2

[controller release];
// (3) decrements retain count to 1

Но для вашего второго примера:

// (2) property setter increments retain count to 2
self.editingViewController = 

    // (1) new object created with retain count of 1
    [[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];

// oops! retain count is now 2

Вызывая метод autorelease для вашего нового объекта перед передачей его установщику, вы просите пул автоматического выпуска получить право собственности на объект и освободить его некоторое время в будущем, поэтому какое-то время у объекта есть два владельца чтобы соответствовать его счету удержания, и все это - труднопреодолимая Дори.

// (3) property setter increments retain count to 2
self.editingViewController = 

    // (1) new object created with retain count of 1
    [[[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil]

        // (2) give ownership to autorelease pool 
        autorelease];

// okay, retain count is 2 with 2 owners (self and autorelease pool)

Другой вариант - назначить новый объект непосредственно переменной экземпляра, а не установщику свойств. Предполагая, что ваш код назвал базовую переменную экземпляра editingViewController:

// (2) assignment to an instance variable doesn't change retain count
editingViewController = 

    // (1) new object created with retain count of 1
    [[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];

// yay! retain count is 1

Это тонкое, но критическое различие в коде. В этих примерах self.editingViewController = x является синтаксическим сахаром для [self setEditingViewController: x], но editingViewController является простой старой переменной экземпляра без какого-либо кода сохранения или копирования, созданного компилятором.

См. Также Почему это приводит к утечке памяти (iPhone)?

4 голосов
/ 22 февраля 2009

Вы можете написать:

self.editingViewController = [[[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil] autorelease];

И я часто делаю это в критических областях без скорости. Проблема состоит в том, что свойство, скорее всего, является свойством «сохранить», что означает, что если вы не отпустите его, объект будет утечкой.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...