2010-01-16 4 views
3

Я работаю над приложением, и я хотел бы убедиться, что я правильно управляю памятью и выпускаю все, что должен. В моем методе viewDidLoad я выделяю некоторые переменные при определении того, какой фон относится к представлению (для интернационализации), и приложение отлично работает, если я их не выпустлю.Управление памятью iPhone

Проблема в том, что если я отпущу переменные, приложение выйдет из строя. Код от viewDidLoad ниже:

// Set the background image based on the phone's preferred language 
NSString *language = [[NSLocale preferredLanguages] objectAtIndex:0]; 
NSString *backgroundImageName = [[NSString alloc] init]; 
backgroundImageName = [NSString stringWithFormat:@"background-%@.png",language]; 
self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:backgroundImageName]]; 

... do some more initialization stuff ... 

// IF THE FOLLOWING ARE RELEASED THE APP WILL CRASH!!! 
//[backgroundImageName release]; 
//[language release]; 

Зачем выпускать backgroundImageName и языковые переменные вызывает приложение к краху?

ответ

6
NSString *language = [[NSLocale preferredLanguages] objectAtIndex:0]; 

Здесь language не нужно быть освобожден, потому что objectAtIndex: autoreleases это для вас. По соглашению, вы являетесь владельцем объекта, если у вас есть alloc ed, new ed, или copy ed, иначе вы этого не сделаете.

self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:backgroundImageName]]; 

Здесь UIColor объект действительно должен быть освобожден (потому что вы alloc эд его).

NSString *backgroundImageName = [[NSString alloc] init]; 
backgroundImageName = [NSString stringWithFormat:@"background-%@.png",language]; 

Вот строка, возвращаемая [[NSString alloc] init] действительно должен быть освобожден (потому что вы alloc эд его). Однако следующая строка изменяет backgroundImageName, чтобы указать на новую строку с автореализацией, потеряв последнюю ссылку на исходную строку, не отпуская ее (утечка памяти). backgroundImageName не должен быть выпущен, поскольку он уже автореализован.

Вы можете избежать утечек, освободив UIColor и устранив неиспользуемую строку. Например:

NSString *backgroundImageName = [NSString stringWithFormat:@"background-%@.png",language]; 

... и ...

UIColor* backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:backgroundImageName]]; 
self.view.backgroundColor = backgroundColor; 
[backgroundColor release]; 
+0

удивительным объяснений. теперь имеет смысл. благодаря! –

0

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

см this для более подробного объяснения

также память management guide является отличным ресурсом узнать больше об управлении памятью в объекте c

0

Вы не создаете строку языка; вы просто возвращаете ссылку. Только методы, которые имеют «новый», «копировать» или «выделять» в них (по соглашению), возвращают неавтореализованные объекты. Для всех других методов предполагается, что вы отбросите переменную, поэтому, если вы хотите сохранить ее, вы ДОЛЖНЫ сохранить ее. Оборотная сторона этого: вы не должны отпускать эти возвращенные объекты, если вы их не сохранили.

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