UIViewController, созданный с помощью initWithNibName: bundle: или через IBOutlet, ведет себя иначе - PullRequest
3 голосов
/ 13 февраля 2010

Я обнаружил странное поведение и хотел бы, чтобы мне объяснили, какое утверждение я делаю неправильно.

В классе AppDelegate недавно созданного проекта WindowBased я добавляю в окно UIViewController.
Я могу сделать это двумя разными способами:
- с IBOutlet. В IB я просто создал экземпляр UIViewController, установил его класс в TestViewController и подключил его (сценарий A кода).
- создание UIViewController с кодом (сценарий B).

    - (void)applicationDidFinishLaunching:(UIApplication *)application {    

#define USE_IBOUTLET YES // Comment this line to switch to scenario B

#ifdef USE_IBOUTLET
    // Scenario A

    [window addSubview:theTestViewController.view];
    [window makeKeyAndVisible];
#endif


#ifndef USE_IBOUTLET
    // Scenario B

    TestViewController *theTestViewControllerProgrammatically;

    theTestViewControllerProgrammatically = [[TestViewController alloc] initWithNibName:nil bundle:nil];

    // According to Apple: "It is a good idea to set the view's frame before adding it to a window.", so let's do it
    [theTestViewControllerProgrammatically.view setFrame:[[UIScreen mainScreen] applicationFrame]];

    [window addSubview:theTestViewControllerProgrammatically.view];

    [window makeKeyAndVisible];
#endif
}

Поскольку я не делал никаких настроек объекта в IB, у меня должно быть одинаковое поведение в обоих сценариях.

Сценарий A, использующий IBOutlet, работает как ожидалось.
Но сценарий B имеет следующие проблемы:
- Вид не в правильном положении (от 20 пикселей до высокого и закрывается строкой состояния).
- Размер представления не изменяется должным образом (например, попробуйте переключить строку состояния In Call)

Почему?

Zip-архив проекта здесь, если вы хотите воспроизвести проблему: http://dl.dropbox.com/u/1899122/code/ProtoWindowBasedStrangeness.zip

Ответы [ 3 ]

2 голосов
/ 18 февраля 2010

Это будет звучать очень глупо после моих многословных ответов, но проблема, с которой вы столкнулись, проста (программно).

Эта строка:

[theTestViewController.view setFrame:[[UIScreen mainScreen] applicationFrame]];

На самом деле должно быть:

[theTestViewControllerProgrammaticaly setFrame:[[UIScreen mainScreen] applicationFrame]];

Вы устанавливали рамку для VC, установленную IB, а не ту, которую вы создали программно.

В любом случае - стоит отметить, что все мои комментарии по-прежнему применимы! Есть еще несколько вещей, которые вам придется делать программно, если вы не используете объекты контроллера IB (например, настраиваете элементы панели навигации)

Пол

1 голос
/ 14 февраля 2010

У меня была очень похожая проблема с вами в том, что я заметил, что объекты VC не все созданы равными! У меня проблема с настройкой элементов панели навигации, я просто не могу этого сделать, когда Владелец Файла является объектом контроллера представления, который я создаю программно. Это работает, только если я разархивирую объекты контроллера IB.

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

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

Например, в вашем MainWindow.xib выберите объект IB VC, и вы можете установить для него атрибуты из палитры инспектора, такие как «Изменить размер представления из NIB». Если вы отмените это и повторно запустите свое приложение, вы увидите, что VC выглядит точно так же, как в сценарии B. Так как вы не можете проверить этот элемент из атрибутов Владельца файла (даже если это UIViewController) ), вы не можете воспользоваться тем, что делается контроллером представления, чтобы дать вам желаемое поведение.

Результатом этого является то, что когда вы используете TestViewController.xib для инициализации вашего объекта VC в коде, ни один из специфических атрибутов IB VC не устанавливается, поэтому создается стандартный болотный UIViewController, и поэтому такие вещи, как " Атрибут Resize View From NIB "и настройка элементов навигации должны быть реализованы самостоятельно.

Я еще не нашел способа воспользоваться преимуществами функциональности контроллеров представления IB, когда я создаю их экземпляры с помощью initWithNibName:bundle:nibBundle (я полагаю, что это все личные вещи, к которым мы не можем получить доступ), но, надеюсь, это может дал вам отправную точку ...

Конечно, я могу быть совершенно неправ, и кто-то заставит меня выглядеть как полный идиот!

Пол

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

Вероятно, в случае B это представление не знает о наличии строки состояния. Вам необходимо соответствующим образом изменить его размер и скорректировать его положение с учетом строки состояния. Это достигается изменением свойств фрейма (размера) и границ (расположения) UIView.

...