2008-09-15 2 views
37

Если у меня есть что-то вроде UILabel, связанного с xib-файлом, нужно ли его выпустить на dealloc моего представления? Причина, о которой я прошу, заключается в том, что я не выделяю ее, что заставляет меня думать, что мне тоже не нужно ее выпускать? например (в заголовке):Нужно ли освобождать ресурсы xib?

IBOutlet UILabel *lblExample; 

в реализации:

.... 
[lblExample setText:@"whatever"]; 
.... 

-(void)dealloc{ 
    [lblExample release];//????????? 
} 

ответ

35

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

@interface MyController : MySuperclass { 
    Control *uiElement; 
} 
@property (nonatomic, retain) IBOutlet Control *uiElement; 
@end 


@implementation MyController 

@synthesize uiElement; 

- (void)dealloc { 
    [uiElement release]; 
    [super dealloc]; 
} 
@end 

Преимущества этого подхода состоит в том, что оно делает семантику управления памятью ясной и ясной, и работает последовательно на всех платформах для всех файлов nib.

Примечание. Следующие комментарии относятся только к iOS до 3.0. С 3.0 и более поздними версиями вместо этого вы должны просто игнорировать значения свойств в viewDidUnload.

Одно из требований здесь заключается в том, что ваш контроллер может распоряжаться своим пользовательским интерфейсом и динамически загружать его по требованию (например, если у вас есть контроллер представления, который загружает представление из файла nib, но по запросу - скажем, под давлением памяти - освобождает его, ожидая, что его можно перезагрузить, если снова потребуется просмотр). В этой ситуации вы хотите убедиться, что при удалении основного вида вы также откажетесь от владения любыми другими выходами, чтобы их тоже можно было освободить. Для UIViewController, вы можете справиться с этой проблемой путем переопределения setView: следующим образом:

- (void)setView:(UIView *)newView { 
    if (newView == nil) { 
     self.uiElement = nil; 
    } 
    [super setView:aView]; 
} 

К сожалению, это приводит к появлению дополнительного выпуска.Поскольку UIViewController в настоящее время реализует свой метод dealloc, используя метод доступа setView: (а не просто просто отбрасывая переменную напрямую), self.anOutlet = nil будет вызываться в dealloc, а также в ответ на предупреждение о памяти ... Это приведет к сбою в dealloc.

Лекарство для обеспечения того, чтобы переменные выходные также устанавливаются в nil в dealloc:

- (void)dealloc { 
    // release outlets and set variables to nil 
    [anOutlet release], anOutlet = nil; 
    [super dealloc]; 
} 
+0

Если у нас есть свойство сохранения, мы не могли бы упростить это, просто говоря self.uiElement = nil; Во всех местах, которые мы хотим отпустить, поскольку это свойство сохранения, оно должно фактически освободить его должным образом, а также установить его на нуль без проблем, одно из преимуществ сохраняемых свойств. – 2010-11-24 13:44:26

+1

Обычно вы выполняете `self.uiElement = nil;` в `viewDidUnload` не в` setView: `. И было бы яснее просто называть `self.anOutlet = nil;` в dealloc. – 2011-01-15 14:38:38

0
+1

@Soeren: Я уже прочитал эту статью и понимаю ее содержимое. Мой вопрос касался объектов, созданных на IB xib, которые он не охватывает. Например: Я никогда не создавал или не выделял ярлык, МАБИ делает все это. Так что мне нужно знать просто: мне нужно его отпустить? – rustyshelf 2008-09-15 04:09:55

0

Вы делаете Alloc этикетку, в некотором смысле, создав его в IB.

Что делает IB, смотрите ваши IBOutlets и как они определены. Если у вас есть переменная класса, которую IB должен назначить ссылку на какой-либо объект, IB отправит вам сообщение сохранения для этого объекта.

Если вы используете свойства, IB будет использовать свойство, которое вы должны установить, а не явно сохранить значение. Таким образом, вы, как правило, отмечают свойства IBOutlet как сохранить:

@property (nonatomic, retain) UILabel *lblExample; 

Таким образом, в случае простого эфира (с использованием свойств или нет), вы должны вызвать высвобождение в вашем dealloc.

+3

Неправильное использование. Если вы не используете свойства (или реализуете свои собственные методы доступа), то независимо от того, должна ли вы быть выпущена, зависит от того, на какой платформе вы находитесь и что является вашим суперклассом. Например, если вы наследуете NSWindowController, вы не выпускаете. – mmalc 2008-10-11 09:50:55

4

Я нашел то, что искал в документах Apple. Короче говоря вы можете настроить свои объекты как свойства, которые высвобождают и сохранить (или просто @property, @synthesize), но вы не должны для таких вещей, как UILabels:

http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/chapter_3_section_4.html#//apple_ref/doc/uid/10000051i-CH4-SW18

0

Любой IBOutlet что Подвижность основного вида вашего Nib не должна быть выпущена, потому что им будет отправлено сообщение автореферата при создании объекта. Единственный IBOutlet, который вы должны выпустить в своем dealloc, - это объекты верхнего уровня, такие как контроллеры или другие NSObject. Все это упоминается в документе Apple, приведенном выше.

+3

Это на самом деле неправильно. Независимо от того, следует ли отправлять объекты верхнего уровня, сообщение о выпуске зависит от того, какую платформу вы используете, и от того, какой класс наследует владелец вашего файла. Например, если он наследуется от NSWindowController, вам не нужно их выпускать. – mmalc 2008-10-10 15:43:03

3

[anOutlet release], anOutlet = nil; 

Часть совершенно излишним, если вы написали setView: правильно.

0

Если вы не установите IBOutlet как свойство, но просто как переменную экземпляра, вы должны освободить его. Это связано с тем, что при initWithNib память будет выделена для всех IBOutlets. Так что это один из особых случаев, которые вы должны выпустить, даже если вы не сохранили или не выделили какую-либо память в коде.

Смежные вопросы