Какао без Interface Builder, инициализировать экземпляр контроллера приложения?
-
05-07-2019 - |
Вопрос
Я не планирую писать приложения без IB, я просто пытаюсь узнать больше о программировании.
Как я могу получить один экземпляр моего класса AppController при запуске? (Обычно он загружается из пера.) И можете ли вы прояснить использование + initialize
и -init
? Если я понимаю, + initialize
вызывается во всех классах при запуске. Как я могу использовать это для создания экземпляра моего AppController с переменными экземпляра, которые составляют мой интерфейс?
Надеюсь, что это имеет смысл, и спасибо за любую помощь.
Решение
+ initalize
отправляется в класс в первый раз, когда он или один из его подклассов получают сообщение в первый раз. Итак, когда вы делаете:
instance = [[[YourClass alloc] init] autorelease];
Это сообщение alloc
вызывает initialize
.
Если вы делаете то же самое с подклассом:
instance = [[[SubclassOfYourClass alloc] init] autorelease];
Это сообщение alloc
будет вызывать + [YourClass initialize]
так же, как и другое (до вызова + [SubclassOfYourClass initialize]
. Но только один из них сделает это - initialize
каждого класса никогда не будет вызываться более одного раза (если только вы сами не вызываете его с помощью [super initialize]
или < code> [SomeClass initialize] & # 8212; так что не делайте этого, потому что метод этого не ожидает.)
-init
, с другой стороны, инициализирует новый экземпляр. В выражении [[YourClass alloc] init]
вы лично отправляете сообщение непосредственно в экземпляр. Вы также можете вызвать его косвенно через другой инициализатор ( [[YourClass alloc] initWithSomethingElse: bar]
) или фабрику удобства ( [YourClass instance]
).
В отличие от initialize
, вы всегда должны отправлять init
(или другой инициализатор, если необходимо) своему суперклассу. Большинство методов инициализации выглядят примерно так:
- (id) init {
if ((self = [super init])) {
framistan = [[Framistan alloc] init];
}
return self;
}
Детали различаются (этот метод или суперкласс или оба могут принимать аргументы, и некоторые люди предпочитают self = [super init]
в отдельной строке и Уил Шипли вообще не назначает self
), но основной Идея та же: вызовите [super init [WithSomething: & # 8230;]]
, убедитесь, что он не вернул nil
, настройте экземпляр, если он не ' t и вернуть все, что вернул суперкласс.
Это подразумевает, что вы можете вернуть nil
из init
, и вы действительно можете это сделать. Если вы сделаете это, вы должны [self release]
, чтобы не пропустить сбойный объект. (Для обнаружения недопустимых значений аргумента альтернативным является NSParameterAssert
, который выдает исключение в случае сбоя утверждения. Относительные достоинства каждого из них выходят за рамки этого вопроса.)
Как я могу использовать это для создания экземпляра моего AppController с переменными экземпляра, которые составляют мой интерфейс?
Лучший способ - это все сделать в main
:
int main(int argc, char **argv) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
AppController *controller = [[[AppController alloc] init] autorelease];
[[NSApplication sharedApplication] setDelegate:controller]; //Assuming you want it as your app delegate, which is likely
int status = NSApplicationMain(argc, argv);
[pool drain];
return status;
}
Вы будете выполнять любые другие настройки в методах делегатов приложения в AppController
.
Вы уже знаете это, но для всех, кто читает это: Перья - ваш друг. Интерфейсный конструктор - ваш друг. Не боритесь с фреймворком, работайте с ним и создавайте свой интерфейс графически, и ваше приложение будет лучше для него.
Другие советы
Набор NIB кажется неудовлетворительным ответом, даже если он представлен в XML (как XIB), потому что нет простого способа сравнить или объединить их с любым стандартным подрывным инструментом или инструментом в стиле SCM. Закодированная информация является хрупкой и не предназначена для редактирования простыми людьми. Как изменения будут представлены в графическом интерфейсе? Буду ли я просматривать каждый атрибут каждого элемента управления и проверять их визуально?
Однако, если поведение приложения записано в коде, есть вероятность, что я смогу понять, что происходит, даже если мне придется держать под рукой множество деталей одновременно.
Предлагаемое решение: используйте NIB верхнего уровня, который кодировал главный архитектор, а затем явно закодируйте остальную часть приложения.
У кого-нибудь есть идея получше?
Еще одно решение проблемы запуска приложения без пера.
Вместо выделения собственного контроллера просто используйте дополнительные параметры в методе NSApplicationMain ()
:
int retVal = NSApplicationMain(argc, argv, @"UIApplication", @"MyAppDelegate");
Это берет на себя все необходимые ссылки.
Тогда единственное, что вам нужно запомнить, - это сделать свое собственное окно и установить его видимым.