Подтвердить что ты не робот

Нужно ли мне выпускать IBOutlets при использовании метода loadNibNamed:?

У меня есть .xib файл, содержащий поддиск UIView и 2 UILabel, связанные с классом с именем Note с точками назначения, назначенными для каждой метки соответствующим образом, определение для этого класса содержит следующее.

@interface Note : UIView {
    IBOutlet UILabel *time;
    IBOutlet UILabel *content;
}

Я создаю это со следующим кодом

NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:@"Note" owner:self options:nil];
note = [nibViews lastObject];
[self addSubview:note];

Теперь, в моей фазе dealloc класса Note, я не выпускаю ни времени, ни контента, но мне интересно, должен ли я?

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

Я предполагаю, что не хочу, потому что я не сохраняю эти объекты в любом месте своего кода, и я не синтезирую их в getter/setters. Но я не знаю достаточно о nib unarchiving, чтобы знать, должен ли я выпускать их на моей фазе dealloc или нет?

4b9b3361

Ответ 1

Это правильно для iPhone; это было бы неверно на Mac.

Однако вам может понадобиться переработать этот код. Небезопасно предположить, что представление будет последним объектом, загруженным из nib. Вместо этого я предлагаю вам либо подключить его к выходу "note" в вашем контроллере просмотра, либо просмотреть список для объекта, который является подклассом Note. (Если вы загружаете несколько Notes и используете опцию "выход", просто убедитесь, что вы добавили одно примечание перед загрузкой другого.)

Ответ 2

Вы должны освободить IBOutlet, даже если вы не пишете или не синтезируете методы доступа. В документации по жизненному циклу NIB говорится, что, хотя для неархивированных объектов изначально задано значение autorelease, счетчик удержания на них накладывается дополнительным 1, когда UIKit подключает все привязки соединения IBOutlet. Поэтому вам необходимо вручную уменьшить выпуск, если вы закончите.

Не очевидно, что UIKit будет делать это, поэтому вы можете предположить, что вы можете просто отключить методы setter/getter и надеяться, что все будет автореализовано. Но это не так.

Обратите внимание, что шаблоны Interface Builder явно освобождают любые IBOutlets, поэтому любой, который вы добавляете, следует обрабатывать аналогичным образом.

Ответ 3

Вам нужно освободить его. См

"Однако, поскольку он восстанавливает иерархию объектов, UIKit восстанавливает соединения между объектами, используя метод setValue: forKey:, который использует доступный метод setter или сохраняет объект по умолчанию, если не доступен метод setter." в Сохранение объекта Nib

Другими словами, поскольку вы не указали эти записи как @property (который неявно объявляет сеттер) или предоставили сеттер напрямую, нет никакого метода setter, и применяется заключительная часть этого параграфа - объект сохраняется по умолчанию.

В вашем методе dealloc() вы должны установить для всех IBOutlets значение nil, используя

self.outletName = nil;

Если сеттер не определен, то setValue автоматически идентифицирует старое значение (убедитесь, что у вас есть NSAutoreleasePool, если он работает в потоке). Если сеттер определен, он будет выполнять любое поведение, которое вы определили. В любом случае, набор в nil будет делать именно то, что нужно, и убедитесь, что у вас нет утечек памяти. НЕ делайте этого

outletName = nil;

Это будет напрямую задавать переменную-член и обходить вызов setValue.

Подробнее см. документацию NSObject setValue: forKey.

Запуск инструмента производительности (утечки) не будет показывать утечку, но вы можете убедиться, что на самом деле существует утечка, если посмотреть на текущее общее количество выделенной памяти.

cf Воздушный источник - управление памятью и NIB

Ответ 4

Вы не сможете извлечь их из памяти, если вы не объявите IBOutlets как свойства и не синтезируете их для ivars:

@interface Note : UIView {
    IBOutlet UILabel *time;
    IBOutlet UILabel *content;
}

@property (nonatomic, retain) IBOutlet UILabel *time;
@property (nonatomic, retain) IBOutlet UILabel *content;

@end


@implementation Note
@synthesize time, content;

// your methods

- (void)dealloc {
     [time release], time = nil;
     [content release], content = nil;
     [super dealloc];
}

@end