Как выпустить IBOutlet, определенный как свойство?
Извините за этот вопрос, но я искал его, и я не нашел ответа на этот случай.
Я изучаю управление памятью для iOS, и я понял, или я так думаю, жизненный цикл представления. Но теперь у меня вопрос о IBOutlet (tat связан с UIImageView в моем файле xib).
У меня есть класс вроде этого:
@interface MyClass : UIViewController
@property (nonatomic, retain) IBOutlet UIImageView *myImage;
Вопрос: как я могу освободить myImage? Это нормально?
- (void)dealloc {
self.myImage = nil;
[super dealloc];
}
- (void)viewDidUnload {
[super viewDidUnload];
self.myImage = nil;
}
Может кто-нибудь объяснить, почему я не могу вызвать метод release в myView (если у вас есть какая-то польза?)?
Спасибо заранее!
Ответы
Ответ 1
В общем случае вы не вызываете release
в свойстве, вы должны называть его соответствующим ivar. Это мой стандартный способ обработки свойств IBOutlet
:
@interface MyClass
@property (nonatomic, retain) IBOutlet UIImageView *myImageView;
@property (nonatomic, retain) IBOutlet UILabel *myLabel;
@end
@implementation MyClass
@synthesize myImageView = _myImageView;
@synthesize myLabel = _myLabel;
- (void)dealloc {
[_myImageView release];
[_myLabel release];
[super dealloc];
}
@end
Ответ 2
IBOutlet не имеет ничего общего с управлением памятью.
Но поскольку он сохраняет свойство, вам нужно освободить его в dealloc.
Итак, ваш код правильный.
Ответ 3
То, что вы делаете, является правильным, и вы обычно shoudnt вызываете выпуск по свойствам, так как установка на nil делает это уже, однако, если у вас есть поддержка ivar для вашего свойства, вы можете вызвать release на этом...
Ответ 4
Там свойство и переменная экземпляра за свойством. Я думаю, что оба они называются myImage (или вы не будете задавать этот вопрос). Вы можете освободить экземпляр двумя способами: либо освободить, либо проиграть ivar, либо просто потерять свойство.
Сгенерированный компилятором сеттер для сохраняемых свойств (например, этот) работает следующим образом: отпустите ссылку на текущий объект (если есть), присвойте новое значение базовому ivar, сохраните его (если не ноль). Поэтому, когда вы назначаете nil свойству, он имеет эффект освобождения текущего значения и замены его на nil.
Для этого используйте
self.myImage = nil; //invoke property setter behind the scenes
Чтобы освободить ивар, используйте
[myImage release];
myImage = nil;
Это функционально эквивалентно приведенному выше коду. Скорей же быстрее. То, о чем вы должны четко понимать, - это различие между свойствами и поддержкой иваров. Именно по этой причине некоторые люди задают им разные имена и синтезируют вот так:
@synthesize MyImage = _MyImage;
Ответ 5
Из Документация Apple:
Устаревшие шаблоны До ARC, правила для управления объектами nib отличных от описанных выше. Как вы управляете объектами зависит от платформы и используемой модели памяти. какой бы ни платформу, для которой вы разрабатываете, вы должны определить торговые точки, используя Objective-C объявленная функция свойств.
Общая форма декларации должна быть:
@property (attributes) IBOutlet UserInterfaceElementClass *anOutlet;
Поскольку поведение выходов зависит от платформы, фактическая декларация отличается:
Для iOS вы должны использовать:
@property (nonatomic, retain) IBOutlet UserInterfaceElementClass *anOutlet;
Для OS X вы должны использовать:
@property (assign) IBOutlet UserInterfaceElementClass *anOutlet;
Затем вы должны либо синтезировать соответствующие методы доступа, или реализовать их в соответствии с объявлением, и (в iOS) релиз соответствующая переменная в dealloc.
Этот шаблон также работает, если вы используете современную среду исполнения и синтезируете переменные экземпляра, поэтому он остается согласованным во всех ситуации.
Ответ 6
Прежде всего: рассмотрите возможность переключения на ARC, если вы не поддерживаете версии iOS до 4.0.
Во-вторых, наилучшая практика написания методов dealloc
говорит о том, что не вызывать сеттеры. Вместо этого, прямо отпустите и запустите свои выходы:
[myImage release], myImage = nil;
Наконец, при объединении методов деинициализации, таких как viewDidUnload
, всегда вызывайте реализацию super
после выполнения вашей собственной работы.
Причина, по которой мы выходим из outlets в viewDidUnload
, состоит в том, что иногда просмотры разгружаются, когда система находится под давлением памяти. Поскольку эти выходы можно легко воссоздать, внедрение viewDidUnload
- это способ повысить производительность и в экстремальных ситуациях не допустить, чтобы ваше приложение было принудительно завершено.
Причина, по которой мы публикуем свойства в dealloc
, - это предотвращение утечек памяти. Поэтому, хотя эти два метода могут выглядеть очень похожими, они служат несколько иным целям.
Ответ 7
Я не понимаю, что вы подразумеваете под "почему я не могу вызвать метод release в myView"
Ваш код кажется правильным для меня, но по соглашению я обычно предпочитаю выпустить iVar непосредственно для сохраненного имущества
Обычно я синтезирую свое свойство следующим образом:
@synthesize myImage = _myImage;
И затем вы освобождаем iVar в методе dealloc
- (void)dealloc {
[_myImage release];
[super dealloc];
}
В любом месте в контроллере я просто использую getter и setter (соглашение о точках)
Ваш viewDidUnload правильный.
Кстати, если вы используете ARC, просто объявите свой IBOutlet
слабым указателем. Он будет автоматически выпущен в ситуациях с низкой памятью и перезагружен, как только ваш просмотр будет загружен обратно.
Надеюсь, это поможет;)