Где инициализировать пользовательский UIView, созданный в интерфейсе Builder?
У меня есть подкласс UIView, который создается в XIB файле. Мне нужно, чтобы он выполнял некоторую инициализацию (настройки некоторых переменных и создание подвью).
Однако я не всегда создаю этот вид через Interface Builder. Я делаю это также программно. В обоих случаях инициализация должна быть одинаковой.
Мой назначенный инициализатор initWithValues:
.
Возникает вопрос: Где выполнить инициализацию?
Поскольку я должен выполнить его в двух разных местах, я решил, что мне нужно реорганизовать его в отдельный метод initialize
(или что-то в этом роде) и вызвать его из initWithValues:
.
Но при загрузке из IB вызываются как initWithCoder:
, так и awakeFromNib
. Из какого метода мне нужно позвонить initialize
? Или мне нужно вызвать initWithValues:
из initWithCoder:
и ничего не делать в awakeFromNib
?
Ответы
Ответ 1
Вы должны использовать initWithFrame:
при инициализации представлений (поскольку это назначенный инициализатор). Следовательно, если у вас initWithValues:
убедитесь, что вы вызываете initWithFrame:
из него.
Что-то вроде этого должно работать для инициализации:;)
- (void)initialize{
//init your ivars here
}
- (id)initWithCoder:(NSCoder *)aCoder{
if(self = [super initWithCoder:aCoder]){
[self initialize];
}
return self;
}
- (id)initWithFrame:(CGRect)rect{
if(self = [super initWithFrame:rect]){
[self initialize];
}
return self;
}
Я собирался добавить еще одно объяснение, но ответ mplappert достаточно ясен. При необходимости используйте awakeFromNib
.
Ответ 2
Это зависит от того, что вам нужно инициализировать. Как только вызов awakeFromNib
вызывается, все выходные и действия подключений вашего представления установлены, что не имеет места в initWithCoder:
. Поэтому, если вам нужно полагаться на эти соединения, используйте awakeFromNib. В противном случае вы можете безопасно выполнить всю свою инициализацию в initWithCoder:
.
Ответ 3
К сожалению, в приведенных выше ответах не учитываются эти вещи:
- (void) awakeAfterUsingCoder - и тот факт, что он вызвал после того, как что-то создается кодером (один раз для каждого представления Xib).
Я вижу, что awakeFromNib страдает от той же судьбы. (Причина, по которой я нашел это)
Другая проблема с инициализацией заключается в том, что для пользовательских представлений можно избежать использования initWithCoder и initWithFrame. И если они называются, ленивая загрузка (хотя и не такая важная для самих представлений) означает, что вы "можете" изменить значения. Я считаю, что сделал это в initWithCoder, но если вы затем инициализируете значения в awakeFromNib, оно отменяется хотя бы один раз.
Я дошел до:
- (void) awakeFromNib (or didMoveToSuperView);
{
BOOL called = NO;
if(!called)
{
called = YES;
}
}
Другой метод, который я использую, - просто вызвать требуемый инициализатор, затем вызвать мой собственный класс или инициализатор, соответствующий суперклассу.
Я тоже ищу надежное одноразовое место, на которое могу положиться. До тех пор я надеюсь, что мои головные боли сохранят следующего человека в течение часа или около того.
Стив