Какао без Interface Builder, инициализировать экземпляр контроллера приложения? - PullRequest
4 голосов
/ 08 марта 2009

Я не планирую писать приложения без IB, я просто пытаюсь узнать больше о программировании.

Как я могу получить один экземпляр моего класса AppController при запуске? (Обычно он загружается из пера.) И можете ли вы прояснить использование +initialize и -init? Если я понимаю, +initialize вызывается на всех классах при запуске. Как я могу использовать это для создания экземпляра моего AppController с переменными экземпляра, которые составляют мой интерфейс?

Надеюсь, что это имеет смысл, и спасибо за любую помощь.

Ответы [ 3 ]

7 голосов
/ 08 марта 2009

+initalize отправляется в класс в первый раз, когда он или один из его подклассов получают сообщение в первый раз. Итак, когда вы делаете:

instance = [[[YourClass alloc] init] autorelease];

Это alloc сообщение вызывает initialize.

Если вы делаете то же самое с подклассом:

instance = [[[SubclassOfYourClass alloc] init] autorelease];

Это сообщение alloc вызовет +[YourClass initialize] так же, как и другое (до того, как также было вызвано +[SubclassOfYourClass initialize]. Но это сделает только один из них - initialize каждого класса никогда не вызывается более одного раза. (Если вы сами не позвоните с помощью [super initialize] или [SomeClass initialize] - не делайте этого, потому что метод не будет этого ожидать).

-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:…]], убедитесь, что он не вернул nil, настройте экземпляр, если он не вернулся, и верните все, что вернул суперкласс.

Это означает, что вы можете вернуть 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.

Вы уже знаете это, но для всех, кто читает это: Перья - ваш друг. Интерфейсный конструктор - ваш друг. Не боритесь с фреймворком - работайте с ним и постройте свой интерфейс графически, и ваше приложение будет лучше для него.

1 голос
/ 10 декабря 2010

Еще одно решение проблемы запуска приложения без пера.

Вместо выделения вашего собственного контроллера, просто используйте дополнительные параметры в методе NSApplicationMain():

int retVal = NSApplicationMain(argc, argv, @"UIApplication", @"MyAppDelegate");

Это берет на себя все необходимые ссылки, которые понадобятся.

Тогда единственное, что вам нужно помнить, - это создать собственное окно и установить его в видимое.

1 голос
/ 31 декабря 2009

Набор NIB кажется неудовлетворительным ответом, даже если он представлен в XML (как XIB), потому что нет простого способа сравнить или объединить их с любым стандартным подрывным инструментом или инструментом в стиле SCM. Закодированная информация является хрупкой и не предназначена для редактирования простыми людьми. Как изменения будут представлены в графическом интерфейсе? Буду ли я проходить через каждый атрибут каждого элемента управления и визуально проверять их?

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

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

У кого-нибудь есть идея получше?

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