Помимо ответа Жака, который является правильным способом решения этой проблемы, у вас была логическая ошибка. В вашем initWithCoder
вы установили self = [super initWithCoder:aDecoder];
, а затем сделали return [self init];
. В init
вы снова перезаписываете себя через self = [super init];
, потенциально полностью изменяя то, что вы сделали в initWithCoder:
. И снова в init
у вас есть return [self init];
, который вызывает бесконечную рекурсию, пока стек не переполнится.
Шаблон для методов init выглядит примерно так:
- (id) initWithFoo:(Bar *)baz {
if ((self = [super initWithFoo:baz])) {
// Do custom initialization.
}
return self;
}
или
- (id) initWithFoo:(Bar *)baz {
if ((self = [super initWithSome:baz other:@"signature"])) {
// Do custom initialization.
}
return self;
}
Также, немного пояснений: - (id) initWithCoder:(NSCoder *)aDecoder
вызывается при десериализации. В этом случае десериализация осуществляется путем загрузки NIB / XIB. Есть коллега, - (void)encodeWithCoder:(NSCoder *)encoder
. Прочитайте Руководство по программированию архивов и сериализации , вы можете найти это полезным, если вы хотите хранить объекты на диске или передавать их по сети.
В любом случае, с NIB, после их загрузки метод awakeFromNib
вызывается для каждого объекта, который хранится в NIB, и служит своего рода инициализатором второго уровня.
Тогда есть initWithFrame:
. Это назначенный инициализатор и тот, который вызывается при программном создании экземпляров UIView.