Как освободить IBOutlet, определенный как свойство? - PullRequest
2 голосов
/ 14 февраля 2012

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

Я изучаю управление памятью для 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 (если у вас есть что-то подобное, это тоже хорошо!)?

Заранее спасибо!

Ответы [ 7 ]

3 голосов
/ 15 февраля 2012

IBOutlet не имеет ничего общего с управлением памятью.

Но так как это свойство сохраняет, вам нужно освободить его в dealloc.

Так что ваш код правильный.

1 голос
/ 14 февраля 2012

Из Документация Apple :

Устаревшие паттерны До ARC правила управления объектами пера отличались от описанных выше.То, как вы управляете объектами, зависит от платформы и используемой модели памяти.Для какой бы платформы вы ни разрабатывали, вы должны определять торговые точки с помощью функции объявленных свойств Objective-C.

Общая форма объявления должна быть:

@property (attributes) IBOutlet UserInterfaceElementClass *anOutlet;

Потому чтоповедение торговых точек зависит от платформы, фактическое объявление отличается:

Для iOS следует использовать:

@property (nonatomic, retain) IBOutlet UserInterfaceElementClass *anOutlet;

Для OS X вы должны использовать:

@property (assign) IBOutlet UserInterfaceElementClass *anOutlet;

Затем вы должны либо синтезировать соответствующие методы доступа, либо реализовать их в соответствии с объявлением, и (в iOS) освободить соответствующую переменную в dealloc.

Этот шаблон также работает, если вы используете современную среду выполнения и синтезируете переменные экземпляра, поэтому он остается согласованным во всех ситуациях.

1 голос
/ 14 февраля 2012

Как правило, вы не вызываете release для свойства, вы бы назвали его на соответствующем иваре. Это мой стандартный способ обработки 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
1 голос
/ 14 февраля 2012

За свойством есть свойство и переменная экземпляра.Я полагаю, они оба называются myImage (иначе вы бы не задавали этот вопрос).Вы можете освободить экземпляр двумя способами - либо освободить и обнулить ivar, либо просто обнулить свойство.

Сгенерированный компилятором установщик для сохраненных свойств (как этот) работает следующим образом: освободить текущую сохраненную ссылку на объект (если есть), присвоить новое значение нижележащему ивару, сохранить его (если не ноль).Поэтому, когда вы присваиваете nil свойству, оно приводит к освобождению текущего значения и замене его на nil.

Для этого используйте

self.myImage = nil; //invoke property setter behind the scenes

Чтобы освободить ивар, используйте

[myImage release];
myImage = nil;

Это функционально эквивалентно приведенному выше коду.Маргинально быстрее.В чем вы должны быть ясны, так это в различии свойств и вспомогательных иваров.По этой причине некоторые люди считают необходимым присваивать им разные имена и синтезировать их следующим образом:

@synthesize MyImage = _MyImage;
1 голос
/ 14 февраля 2012

То, что вы делаете, правильно, и вы, как правило, должны вызывать release для свойств, поскольку установка nil уже делает это, однако, если у вас есть резервный ivar для вашего свойства, вы можете вызывать release для этого ...

0 голосов
/ 14 февраля 2012

Я не совсем понимаю, что вы имеете в виду, «почему я не могу вызвать метод release в myView»

Ваш код мне кажется правильным, но по договоренности я обычно предпочитаю выпускать iVar напрямую дляоставшееся свойство Я обычно синтезирую свое свойство следующим образом:

@synthesize myImage = _myImage;

И затем вы освобождаете iVar в методе dealloc

- (void)dealloc {
     [_myImage release];
     [super dealloc];
}

В другом месте в контроллере я просто иду наgetter и setter (соглашение о точках)

Ваш viewDidUnload правильный.

Кстати, если вы используете ARC, просто объявите ваш IBOutlet как слабый указатель.Он будет автоматически освобожден при нехватке памяти и перезагружен, как только ваш вид снова загрузится.

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

0 голосов
/ 14 февраля 2012

Прежде всего: рассмотрите возможность перехода на ARC, если вы не поддерживаете версии iOS до 4.0.

Во-вторых, лучшая практика написания dealloc методов гласит: не вызывать сеттеры. Вместо этого прямо отпустите и обнулите ваши торговые точки:

[myImage release], myImage = nil;

Наконец, при объединении методов деинициализации, таких как viewDidUnload, всегда вызывайте реализацию super после выполнения своей собственной работы.

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

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

...