Не должен IBOutlet, чтобы быть собственность и синтезированных?


в большинстве примеров я вижу следующую настройку IBOutlets:



(Example A)

FooController.h:

@interface FooController : UIViewController {
    UILabel *fooLabel;
}

@property (nonatomic, retain) IBOutlet UILabel *fooLabel;

@end

FooController.m:

@implementation FooController

@synthesize fooLabel;

@end

но это работает также отлично (обратите внимание: нет свойства и нет синтезировать):



(Example B)

FooController.h:

@interface FooController : UIViewController {
    IBOutlet UILabel *fooLabel;
}

@end

FooController.m:

@implementation FooController

@end

есть ли какие-либо недостатки определения IBOutlets, как в примере B? Как утечка памяти? Кажется, работает нормально, и я предпочитаю не выставлять IBOutlets как общедоступные свойства, поскольку они не используются как таковые, они используются только в реализации контроллера. Определение его в трех местах без реальной необходимости не поражает мне же очень сухо (не повторяйтесь).

4 53

4 ответа:

в Mac OS X IBOutlets подключаются следующим образом:

  1. найдите метод set:. Если он существует, назовите его.
  2. Если метод не существует, найдите переменную экземпляра с именем , установите ее без удержания.

на iPhone OS IBOutlets подключаются следующим образом:

  1. вызов [объект setValue: outletValue forKey:@ " "]

поведение заданного значения для ключа сделать что-то вроде этого:

  1. найдите метод set:. Если он существует, назовите его.
  2. Если метод не существует, найдите переменную экземпляра с именем , установите ее и сохранить его.

Если вы используете свойство, вы попадете в "найдите метод set:..." случай на обеих платформах. Если вы просто используете переменную экземпляра, то у вас будет другое поведение сохранения/выпуска на Mac OS X VS iPhone OS. Нет ничего плохого в использовании переменной экземпляра, вам просто нужно иметь дело с этой разницей в поведении при переключении между платформами.

вот ссылка на полную документацию на эту тему. https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html#//apple_ref/doc/uid/10000051i-CH4-SW6

в Mac OS X IBOutlets не сохраняются по умолчанию. Это противоположно поведению на iPhone OS: на iPhone OS, если вы не объявляете свойство, оно сохраняется, и вы должны освободить это свойство в dealloc метод. Кроме того, 64-разрядная среда выполнения может синтезировать переменные экземпляра с помощью объявлений свойств. Это означает, что когда-нибудь переменные экземпляра (с IBOutlet) могут быть опущены.

по этим причинам он более однороден и совместимы для создания всегда свойство и использовать IBOutlet только в собственность. К сожалению, он также более многословен.

в вашем первом примере, вы всегда должны освободить розетку в dealloc метод. Во втором примере вы должны выпустить розетку только с iPhone OS.

конечный результат точно такой же, но вы должны держать несколько вещей в виду:

  • при использовании полей экземпляра в качестве выходов, вы не должны выпускать их в dealloc.

  • при использовании свойств, которые имеют атрибут (сохранить), вы должны освободить имущество в dealloc (через self.property=nil или отпуская переменную поддержки). Это делает его намного более прозрачным относительно того, что происходит на.

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

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

второй пример (без свойства и без синтеза) с IBOutlet используется, когда разработчик "назначает" UILabel (Button, View и т. д.) В Построителе интерфейса-путем перетаскивания IBOulet в Метка или другой компонент представления. На мой взгляд, предыдущее действие перетаскивания (метка на вид) также добавляет подвид, метку к виду-и так далее. Метка сохраняется видом; вид сохраняется окном; окно сохраняется владельцем файла. Владельцем файла обычно является ваш документ, который загружается в main.

вы заметите, что при переходе через вашу программу (путем добавления awakeFromNib

- (void)awakeFromNib
{
    [fooLabel blahblah];
}

у этого дурака уже есть память адрес.

это потому, что метка была инициализирована из пакета файлов (файл nib) с использованием не init, а initWithCoder. Который по существу десериализует filestream в объект-а затем устанавливает переменную IBOutlet. (Мы все еще говорим о методе IBOutlet).

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

  call [object setValue:outletValue forKey:@"<OutletName>"]

, который является наблюдателя/наблюдаемого паттерна. Этот шаблон требует Ссылки на наблюдаемый объект каждый Наблюдатель в наборе / массиве. Изменение значения будет повторять набор/массив и одинаково обновлять всех наблюдателей. Этот набор уже сохранит каждого наблюдателя, таким образом, отсутствие сохранения в iOS.

дальше и дальше идет спекуляция.

похоже, что случаи, когда вы используете Interface Builder, то

 @property (nonatomic, retain) IBOutlet UILabel *fooLabel;

возможно, следует изменить на

@property (nonatomic, weak) IBOutlet UILabel *fooLabel;

или @property (nonatomic, assign) IBOutlet UILabel * fooLabel;

и тогда это не должно быть выпущен в методе dealloc. Кроме того, он будет удовлетворять требованиям OSX и iOS.

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

тем не менее, это может не иметь значения, если представление является постоянным в течение всей жизни вашей программы. В то время как метка в модальном диалоговом окне (open, close, open, close) может фактически иметь избыточное удержание и утечку за цикл. И это потому, что (опять же спекуляция) каждое закрытое диалоговое окно сериализуется в файловую систему и таким образом сохраняется положение и размер x,y, а также его подвиды и т. д. И затем десериализовать ... на следующем сеансе open (против того, чтобы сказать minimiz или hidden.)