2009-02-22 2 views
4

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

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

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

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

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

Спасибо!

ответ

8

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

По соглашению в какао и какао-прикосновении любой объект, созданный с использованием [[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 на свой новый объект, прежде чем передавать его на setter, вы попросите пул авторесурсов взять собственность на объект и выпустить его некоторое время в будущем, поэтому на некоторое время у объекта есть два владельца, чтобы соответствовать его счету удержания, и все очень сложно.

// (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 является простой старой переменной экземпляра без кода сохранения или копирования, сгенерированного компилятором.

Смотрите также Why does this create a memory leak (iPhone)?

+0

@property (сохранить) РедактированиеViewController * editViewController; // (2) приращения уставки свойств сохраняются до 2 self.editingViewController = // (1) новый объект, созданный с сохранением count 1 [[EditingViewController alloc] initWithNibName: @ «EditingView» bundle: nil]; // Упс! сохранить счет сейчас 2 Это неправда. Метод setter, созданный компилятором, освободит объект, переданный как параметр, и сохранит свойство. Таким образом, счет сохранения будет равен 1, и проблем нет. –

4

Вы могли бы написать:

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

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

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

+0

даже если это свойство копирования, вы бы просочиться. – 2009-02-22 09:31:57

+0

Я думаю, что вы пропустили вызов авторекламы в конце. –

Смежные вопросы