#objective-c #cocoa-touch #memory-management #properties #iboutlet
#objective-c #cocoa-touch #управление памятью #свойства #iboutlet
Вопрос:
Это то, что я должен был прояснить давно, но мне просто нужно знать наилучшую практику освобождения в следующем сценарии.
В моем заголовочном файле я объявляю ссылку на IBOutlet
следующим образом:
@interface Test : UIViewController {
UIButton *_loginBtn;
}
@property (nonatomic, retain) IBOutlet UIButton *loginBtn;
И в файле реализации я связываю переменную экземпляра со свойством и освобождаю ее следующим образом:
@implementation Test
@synthesize loginBtn = _loginBtn;
...
- (void) dealloc {
[_loginBtn release];
self.loginBtn = nil;
[super dealloc];
}
- (void) viewDidUnLoad {
[_loginBtn release];
self.loginBtn = nil;
[super viewDidUnLoad];
}
Правильно ли я определил освобождение переменной экземпляра и присвоил свойству значение nil
и сделал это в обоих методах viewDidUnLoad
and dealloc
?
Комментарии:
1. На самом деле я бы ожидал, что [_loginBtn release]; в сочетании с self.loginBtn = nil; произойдет сбой. Первый освободит значение, но оставит его установленным. Затем второй попытается снова освободить значение, установив для него значение nil. Это было бы двойным выпуском.
Ответ №1:
В in нет необходимости self.loginBtn = nil;
dealloc
, предыдущая строка освободила его. Лучше не использовать свойство для его освобождения в dealloc. Причина освобождения vs для установки свойства в nil заключается в том, что установщик является вызовом метода, а класс находится в процессе разрушения, и ситуация может быть нестабильной.
При viewDidUnLoad
освобождении любых свойств, IBOutlet
с self.theOutlet = nil;
которыми они связаны, в данном случае _loginBtn release];
они не нужны и являются избыточными. Также освободите любые другие объекты, которые вы можете легко воссоздать.
Если используются свойства, они должны использоваться для всех обращений в классе с двумя исключениями: init и dealloc. В обоих этих случаях класс частично завершен. В этих двух случаях лучше всего использовать ivar непосредственно в init
(при необходимости) и release
в dealloc
.
Комментарии:
1. должен ли я просто устанавливать IBOutlets на nil в viewDidUnload или я также должен устанавливать такие свойства, как массивы, на nil (опять же в viewDidUnload)?
2. Основная проблема здесь — предупреждения о памяти и памяти. При предупреждении о памяти система может выгружать представления, которые не отображаются, чтобы освободить необходимую память. Проще всего установить для IBOutlets значение nil, освободив их, система повторно загрузит их при повторной загрузке представления. Если у вас есть объекты, которые вы можете легко воссоздать, рассмотрите возможность их освобождения, вам придется воссоздать их в viewDidLoad . Чем больше вы помогаете ситуации с памятью, тем дольше ваше приложение живет в фоновом режиме, ожидая повторного запуска.
3. Если приложение достаточно загружено памятью, чтобы получать предупреждения о нехватке памяти, когда оно находится на переднем плане, обязательно освободите как можно больше, жизнь и необходимость перезагрузки лучше, чем завершение.
Ответ №2:
Нет, это неверно. Сначала отпуская _loginBtn, а затем устанавливая для свойства значение nil, вы освобождаете экземпляр дважды. Правильный способ сделать это — освободить _loginBtn, а затем установить _loginBtn равным нулю.
Комментарии:
1. Добро пожаловать. Одно замечание, поскольку я не могу прокомментировать другой ответ. Во многих случаях предпочтительнее вызывать release вместо присвоения nil свойству, поскольку освобождение в свойстве реализуется с использованием автоматического освобождения, что задерживает освобождение и приводит к накладным расходам. Я бы выбрал release, а затем установил local равным нулю, чтобы избежать несчастных случаев с последующими частями метода dealloc с использованием свойства.