Объявление IBOutlet внутри или снаружи @interface? - PullRequest
12 голосов
/ 08 января 2011

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

IBOutlet прилагается к собственности

#import <UIKit/UIKit.h>
#import "CustomCell.h"

@interface CustomTableViewController : UITableViewController {
  CustomCell *customCell;
}
@property (nonatomic, retain) IBOutlet CustomCell *customCell;
@end

А некоторые заявляют вот так:

IBOutlet, прикрепленный к объявлению внутри интерфейса

#import <UIKit/UIKit.h>
#import "CustomCell.h"

@interface CustomTableViewController : UITableViewController {
  IBOutlet CustomCell *customCell;
}
@property (nonatomic, retain) CustomCell *customCell;
@end

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

Большое спасибо :)

Ответы [ 3 ]

12 голосов
/ 08 января 2011

Оба они все еще находятся "в интерфейсе", поэтому ваш заголовок немного запутан, но я понимаю, что вы спрашиваете.

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

Я предпочитаю использовать выходы для свойств, потому что я думаю, что это делает управление памятью объектов, загруженных из пера, намного более четким. Взгляните на управление памятью nib-объектов , и я думаю, вы поймете, что я имею в виду.

Объекты в файле пера создаются с счетом сохранения 1 и затем автоматически высвобождаются. Поскольку он перестраивает иерархию объектов, UIKit восстанавливает соединения между объектами, используя setValue: forKey :, который использует доступный метод установки или сохраняет объект по умолчанию, если метод установки не доступен. Это означает, что (при условии, что вы следуете шаблону, показанному в «Розетках»), любой объект, для которого у вас есть розетка, остается действительным. Однако, если есть объекты верхнего уровня, которые вы не храните в торговых точках, вы должны сохранить либо массив, возвращенный методом loadNibNamed: owner: options:, либо объекты внутри массива, чтобы предотвратить преждевременное освобождение этих объектов.

IBOutlet ivars вызовет сеттеры для этих иваров, если они существуют, и непосредственно сохранит объект, загруженный из пера, если сеттер не найден.

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

Наконец, я утверждаю, что IBOutlets являются частью открытого интерфейса класса, и поэтому лучше использовать методы (через свойство) для работы с ними, чем использовать -setValue: forKey: для манипулирования вспомогательными ivars, деталь реализации.

1 голос
/ 08 января 2011

Два стиля являются взаимозаменяемыми, нет никакой разницы в сгенерированном коде или способе загрузки объектов из пера.Действительно.

Однако оба стиля имеют избыточную строку.Просто пропустите объявление ivar.В современной среде выполнения достаточно строки

@property (nonatomic, retain) IBOutlet CustomCell *customCell;

.

Если у вас сложный проект, я предлагаю переместить все выходы из открытого интерфейса в отдельный файл заголовка.Большинство выходов имеют закрытый интерфейс, единственная причина, по которой они есть в заголовке, заключается в том, что Interface Builder может их найти.

0 голосов
/ 08 января 2011

Вы можете объявить оба пути, на самом деле нет никакой разницы.

Но вот в чем дело:

Если вам нужно, чтобы у вашего класса был какой-то ивар с особым поведением, или к нему нужно обращаться извне и т. Д., И это должно быть свойством, тогда я скажу, что у вас есть 2 варианта на выбор (прикрепленный свойство и внутри интерфейса класса).

Если это не ваш случай, не создавайте свойство, в этом нет необходимости, просто сделайте это внутри интерфейса вашего класса.

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

...