Каков обычный шаблон для реализации цепочки `-init` при создании подкласса UIView? - PullRequest
1 голос
/ 07 октября 2010

Когда я создаю объект для использования в NIB, объект должен реализовывать -initWithCoder:. Однако я не могу понять регулярную схему реализации этого.

Я использовал этот код.

- (id) initWithCoder:(NSCoder *)aDecoder
{
 if(self=[super initWithCoder:aDecoder])
 {
     // initialize my object.
 }
 return self;
}

Но я должен сделать такой же код для UIView, созданный с помощью кода, подобного этому.

- (id) initWithCoder:(NSCoder *)aDecoder
{
 if(self=[super initWithCoder:aDecoder])
 {
     // initialize my object.
 }
 return self;
}
- (id) initWithFrame:(CGRect)frame
{
 if(self=[super initWithFrame:frame])
 {
     // initialie my obejct.
 }
 return self;
}

Я чувствую что-то не так. Любые рекомендации?

* Исходная логика инициализации может быть извлечена в новый метод, но это не точка.

Ответы [ 2 ]

4 голосов
/ 07 октября 2010

Используйте awakeFromNib для инициализации UIView, который создается из файла NIB.Если вы хотите сделать его общим, чтобы его можно было создать либо из файла NIB, либо программно, создайте метод, подобный configureObject, и вызовите его как из назначенного инициализатора (часто initWithFrame :), так и из awakeFromNib.

- (void)configureObject {
    // Do initialization here
}

- (id)initWithFrame:(CGRect)frame {
    if(self = [super initWithFrame:frame])
    {
        [self configureObject];
    }

    return self;
}


- (void)awakeFromNib {
    [self configureObject];
}
1 голос
/ 07 октября 2010

Помимо ответа Жака, который является правильным способом решения этой проблемы, у вас была логическая ошибка. В вашем 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...