Контроллер представления, который может быть создан как программно, так и в IB? - PullRequest
3 голосов
/ 29 июня 2009

Контроллер представления FooViewController должен выполнить некоторую инициализацию при его создании (само по себе, а не управляемого представления - до того, как представление даже будет загружено).

Я хочу иметь возможность создать его двумя способами:

  1. Программно, возможно с некоторыми аргументами:

    FooViewController *fooViewController = [[[FooViewController alloc] initWithSomeData:data] autorelease];
    [self.navigationController pushViewController:fooViewController animated:YES];
    
  2. В Интерфейсном Разработчике.

Для (1) я бы написал инициализаторы так:

- (id)initWithSomeData:(Data *)data     // designated initializer
{
    if (self = [super initWithNibName:@"FooView" bundle:nil]) {
        self.title = "Foo";
        // perform initialization
    }
    return self;
}
- (id)init
{
    return [self initWithSomeData:nilOrSomeDefaultValue];
}

// ... other initializers that call the designated initializer

(Я жестко прописываю имя пера, поскольку контроллер всегда использует одну и ту же конфигурацию представления и потому, какое представление он использует, вообще не касается вызывающих абонентов)

При создании в Интерфейсном Разработчике я бы хотел, чтобы конечный результат был таким же, как если бы объект был инициализирован без параметров init.

Теперь, если я просто сделаю:

- (id)initWithCoder:(NSCoder *)decoder
{
    return [self init];
}

Свойства title, wantsFullScreenLayout и nibName, установленные в Инспекторе в Интерфейсном Разработчике, будут игнорироваться, но это нормально. NibName жестко закодировано в init, и там устанавливается title на случай, если контроллер в любом случае создается программно.

Проблема в том, что parentViewController не установлен (по умолчанию initWithCoder: установит его на основе иерархии объектов в NIB).

Как я могу получить родительский объект из пера? Затем я бы изменил initWithCoder: на что-то вроде:

- (id)initWithCoder:(NSCoder *)decoder
{
    if (self = [self init]) {
        _parentViewController = [decoder parentObject];
    }
    return self;
}

Или я должен использовать какой-то другой подход для создания контроллеров, которые могут быть созданы как программно, так и в IB?

Ответы [ 2 ]

0 голосов
/ 29 июня 2009

Почему бы не выполнить инициализацию в viewDidLoad - при создании вне IB вы можете установить начальные значения с помощью некоторых других методов или свойств после инициализации, но до вызова viewDidLoad.

0 голосов
/ 29 июня 2009

Не, не, не пытайтесь создать viewcontroller, который работает как с пером, так и без него. Это будет кошмар, потому что nibloading использует некоторые из обычных точек входа и предоставляет новые, и это будет хрупким по отношению к ревизиям ОС.

Что вы можете сделать, это заставить контроллер представления всегда загружаться с кончика, а затем использовать удобный инициализатор для прохождения через кончик:

- (id) init {
  return [[[self class] alloc] initWithNibNamed:@"MyNibName" bundle:nil];
}

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

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