Подкласс UIViewController, инициализирующий себя из .xib, не может использовать UINavigationItem? - PullRequest
2 голосов
/ 12 февраля 2010

Мне, наконец, пришлось отказаться от неустанного поиска ответа на этот вопрос, так как я просто не могу найти никого, кто его задавал раньше! Так что надеюсь, что кто-то может дать некоторое представление. Я начну с объяснения того, что я могу сделать, затем сравню это с тем, что я не могу понять, как это сделать.

Предположим, у меня есть собственный VC под названием RootViewController. Он содержит выход типа MyViewController. Мой RootViewController имеет .xib, который содержит универсальный объект VC, перетаскиваемый из палитры IB, которому присвоен тип класса MyViewController. Я установил элемент кнопки правой панели в UIBarButtonItem под названием «Отмена». RootViewController разархивирует его .xib, подключает выход к объекту MyViewController, я помещаю указанный объект в стек навигации, который отображается, как и ожидалось, у меня есть вид и кнопка на панели навигации с надписью «Отмена».

Проблема с этим подходом заключается в том, что я хочу, чтобы MyViewController можно было повторно использовать для любого объекта, который может захотеть создать MyViewController. Следовательно, это означает, что «Владельцем файла» может быть любой объект. Ранее это был RootViewController, но что, если другой объект хотел создать экземпляр MyViewController? Владелец файлов будет отличаться каждый раз. Я также хочу, чтобы он мог полностью инициализировать себя из прекрасно автономного .xib. В основном, я хочу сделать это:

MyViewController *myVC = [[MyViewController alloc] init];

И в реализации MyViewController я пишу это:

- (id)init
{
    if ( self = [super initWithNibName:@"MyViewController" bundle:nil] )
    {
        // Initialisation
    }
}

Это аккуратно скрывает имя .xib, используемое для инициализации VC, использует все добро, которое IB дает мне при настройке контроллера и представления, а MyViewController всегда является владельцем, это означает, что я тоже решаю проблему владельца файла - он будет работать для любого типа класса, который его создает.

Итак, чтобы добиться этого, я создаю .xib, устанавливаю владельца файла типа MyViewController, добавляю UINavigationItem и добавляю UIBarButtonItem. Теперь у меня есть .xib структурно такой же, как и раньше, за исключением того, что он не использует универсальный объект VC IB как отдельный объект верхнего уровня, .xib является определением VC, а не чем-то, что содержит определение VC.

Итак, учитывая, что Владелец Файла является MyViewController и как подкласс UIViewController (предположительно, наследует все, что вы получаете, используя UIViewController из палитры IB), тогда я должен унаследовать все функциональные возможности его суперкласса ... За исключением того, что это не «т.

Когда .xib не разархивирован, он не подключает UINavigationItem. Поэтому, когда он помещается в стек навигации, ни один из элементов панели кнопок не отображается.

Свойство UIViewControllers navigationItem доступно только для чтения, поэтому создание выхода для него в iPhone OS 3.0 не рекомендуется.

Итак, в конце концов, как на самом деле код загрузки пера может связать версию объекта VC IB с элементом навигации? И почему, даже если мой объект является UIViewController через наследование, он не будет делать это для моего объекта? Я совершенно не в состоянии понять это ...

Спасибо, что прочитали это далеко! Надеюсь услышать от вас, гуру

Ответы [ 2 ]

0 голосов
/ 16 февраля 2010

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

По сути (и это будет звучать очевидно) UIViewController не является прокси-объектом! Это не сразу очевидно, поскольку мы все привыкли к мысли, что если какие-либо два объекта наследуются от одного и того же базового класса, то их реализации одинаковы, и они будут вести себя точно так же (при условии отсутствия настройки в наследующем классе). Но тип объекта IB отличается от атрибута класса, который вы можете назначить этим объектам. Они не оба являются объектами UIViewController, потому что их атрибут класса установлен таким образом.

Простая установка атрибута класса этих объектов в IB не означает, что эти объекты теперь являются объектами UIViewController. Объект View Controller остается объектом View Controler, а прокси-объект остается прокси-объектом. Что касается IB, то оба они очень разные звери, просто у них один и тот же атрибут класса.

Просто взгляните на .xib, и вы обнаружите, что ваши объекты IB View Controller были заархивированы следующим образом:

<object class="IBUIViewController" id="...">
    ...
</object>

И прокси-объект (для которого установлен подкласс UIViewController) архивируется так:

<object class="IBProxyObject" id="...">
    ...
</object>

Как вы видите, оба они очень разных типов, один из них является IBUIViewController, а другой - IBProxyObject - и тогда это начинает иметь смысл - вы не можете навязывать атрибуты контроллера VC объекту типа IBProxyObject.

Также интересно отметить, что типом класса является IBUIViewController объект, а не просто UIViewController объект. Является ли это просто соглашением об именах или нет, я не знаю, но это может также означать, что объекты контроллера представления IB обертывают экземплярный объект VC, или это объект фабрики для него. Например, вы можете установить атрибут «Resize View From NIB» в объекте контроллера представления IB - но я не могу найти эквивалентное свойство или методы в справочных документах UIViewController.

Итак, в заключение, если вы пытаетесь создать экземпляр объекта программно, а не использовать выходы для объекта IB, будьте готовы реализовать некоторую инициализацию, которую в противном случае предоставила бы версия IB ...

0 голосов
/ 12 февраля 2010

Только UINavigationController устанавливает свойство навигационного элемента UIViewController. Сделайте что-то вроде этого:

MyViewController *viewController = [[MyViewController alloc] init];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];

Предполагается, что вы находитесь в контроллере представления, в котором уже есть контроллер навигации. После того, как вы нажмете его, вы сможете получить доступ к навигационному элементу из MyViewController.

...