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

Надеюсь, это поможет;)