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

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

4b9b3361

Ответ 1

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

  • Ищите метод с именем set <OutletName> :. Если он существует, вызовите его.
  • Если никакого метода не существует, найдите переменную экземпляра с именем <OutletName> , установите ее без сохранения.

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

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

Поведение заданного значения для ключа состоит в том, чтобы сделать что-то вроде этого:

  • Ищите метод с именем set <OutletName> :. Если он существует, вызовите его.
  • Если никакого метода не существует, найдите переменную экземпляра с именем <OutletName> , установите ее и сохранить.

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

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

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

что fooLabel уже имеет адрес памяти.

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

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

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

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

Далее, а остальные - спекуляции.

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

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

следует изменить на

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

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

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

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

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