Шаблон приложения для iOS на основе просмотра
-
10-10-2019 - |
Вопрос
Я прочитал руководство Apple «Ваше первое приложение для iOS», и все, что мне кажется кристально ясным для меня. Однако, когда я пытаюсь понять, как работает шаблон приложения для iOS, основанный на просмотре, я сталкиваюсь с некоторыми интересными загадками.
Я понимаю, что приложение получает основное имя файла NIB (обычно, mainwindow.xib) образует файл *-info.plist. Чего я не понимаю, так это то, как XCODE узнает, какой файл NIB связан с контроллером, который создается с помощью этого шаблона приложения, основанного на представлениях по умолчанию. В руководстве вы начинаете с приложения на основе окон, и вам нужно написать «что-то вроде:
MyViewController *aViewController = [[MyViewController alloc]
initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]];
[self setMyViewController:aViewController];
что имеет смысл. Тем не менее, выясняется, что в шаблоне приложения на основе просмотра такого нет, и что эта спецификация NIB на самом деле не была на самом деле необходима в первую очередь, если вы создали свой подкласс UiviewController с опцией «с XIB для пользовательского интерфейса "Проверено. Мой вопрос: как XCODE узнает, какой NIB связан с этим контроллером, то есть он хранит это соединение в некоторых файлах или, возможно, каким -то соглашением (возможно, то же имя для контроллера и файла NIB)? Более того, откуда это «загружено из подзаголовника» в «MyViewBasedAppController» из «MyViewBasedAppController», проведенного в представлении интерфейсного строителя на контроллере в Mainwindow.xib? Это определенно не там, когда я добавляю контроллер вручную, поэтому мне любопытно, что магия делает Xcode за моей спиной, когда я думаю, что я просто выбираю простой шаблон кода.
Решение
Если вы посмотрите в целевой информации (дважды щелкните цель, чтобы поднять это), вкладка «Свойства», вы увидите имя основного файла NIB. Слова «nib» и «xib» взаимозаменяемы для этих целей; XIB - это просто более новая альтернатива для NIB.
Это будет «Mainwindow» только из шаблона. Если вы откроете Mainwindow.xib, вы увидите, что есть объект с именем «Degate» [Имя проекта], и если вы покажете инспектора и проверьте на вкладке «Я», вы увидите тип класса, который Назван наверху. Если вы проверите вкладку «Соединения» (стрелка с правой стороной), вы увидите, что владелец файла (который является самой UIApplication) имеет свое свойство «делегата».
Вы также увидите, что у него есть розетка под названием «ViewController». Это подключено к другому объекту в XIB, называемом «контроллер представления проекта». Проверьте тип на этом, и вы увидите, что это тот тип контроллера представления, который XCode добавил к вашему проекту. Глядя на его атрибуты (первая вкладка в Инспекторе, с графикой слайдера), вы также увидите, что отдельный файл NIB определяется как содержащий его основные детали.
Ради аргумента, предположим, что я назвал свой проект «Nibtest» и не внес никаких изменений.
Во время выполнения устройство загружает info.plist. Там видит, что делегат имеет тип Nibtestappdelegate. Таким образом, это создаст экземпляр экземпляра класса Nibtestappdelegate и установит на него свойство делегата UIAPLICATION.
Затем из Mainwindow.nib будет увидеть, что у Nibtestappdelegate есть участник с именем ViewController типа NibtestViewController. Таким образом, это создаст экземпляр этого и установит свойство ViewController на экземпляре NibtestAppDelegate, который он только что создал для него.
Делая это, это откроет другой XIB и продолжит делать те же шаги.
Objective-C имеет полностью рефлексивную среду выполнения, поэтому вы можете создавать создание объектов по имени класса во время выполнения. Это одно из различий между Objective-C и C ++, например.
Xcode не генерирует какого -либо скрытого кода и не полагается на какие -либо скрытые соглашения об именах. Все это выясняется во время выполнения ОС.
Изменить: например, вместо вашего примера:
MyViewController *aViewController = [[MyViewController alloc]
initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]];
Вы могли бы сделать:
MyViewController *aViewController = [[NSClassFromString(@"MyViewController") alloc]
initWithNibName:@"MyViewController" bundle:[NSBundle mainBundle]];
Они будут работать одинаково, пока MyViewController существует в программе или в более широком времени выполнения.
Вы можете альтернативно передать любой другой строковый объект, который вам нравится NSClassFromString
. Анкет Даже спросите пользователя об этом, если хотите (хотя это было бы действительно плохой идеей по соображениям безопасности).