Подтвердить что ты не робот

Смещение по UIWindow addSubview

У меня есть приложение на основе UITabBar, которое отлично работает. Однако при определенных обстоятельствах я показываю другой UIViewController. Теперь, что меня беспокоит, я должен правильно настроить рамку для Test nib (и только Test nib!). (В противном случае представление находится ниже строки состояния).

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

        UIViewController *vc = [[UIViewController alloc] initWithNibName:@"Test" bundle:nil];

        // FIXME this should NOT be required
        CGRect r = vc.view.frame;
        r.origin.y += 20;
        vc.view.frame = r;

        [window addSubview:vc.view];
        [window makeKeyAndVisible];
        return;
    }

    [window addSubview:tabViewController.view];
    [window makeKeyAndVisible];
}

Так что, может быть, что-то не так с тестовым наконечником? Не может быть. Испытательный наконечник работает по желанию в новом новом проекте. И новый чистый нить показывает те же симптомы. Так что что-то должно быть неправильно с кончиком MainWindow, правильно? Но UITabBarController отображается просто отлично.

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

4b9b3361

Ответ 1

Добавление корневого представления в UIWindow может быть сложным, так как окно всегда перекрывает строку состояния. Поэтому рамка вашего корневого представления должна быть reset до [[UIScreen mainScreen] applicationFrame], чтобы она не перекрывала строку состояния. Мы обычно не должны беспокоиться об этом, потому что UIViewController меняет рамки для нас... за исключением случаев, когда этого не происходит. Здесь сделка:

  • Если вы создаете свой контроллер представления и его вид в том же NIB, и вы вставьте представление под представлением контроллер, будет автоматически настроить рамку просмотра.
  • Если вы создаете свой контроллер представления и его вид в том же NIB, но вы подключить представление к представлению контроллер через контроллер вместо того, чтобы вставлять его, контроллер не будет автоматически настраивать рамку просмотра.
  • Если вы создаете свой контроллер представления в одном NIB и подключаете его к представлению, определенному в отдельном NIB, задав свойство "NIB Name" в контроллере представления, он будет отрегулировать вид кадр автоматически, но , только если у вас также установлен флажок "Изменить размер из NIB".
  • Если вы создаете свой контроллер просмотра, вызывая -initWithNibName: bundle:, не будет автоматически настраивать рамку просмотра.
  • UITabBarController ожидает, что его представление будет добавлено в виде корневого представления окна, и поэтому всегда настраивает собственный кадр представления, чтобы он соответствовал рамке приложения автоматически. (В результате вы заметите странный 20-пиксельный зазор, если вы когда-либо добавляли представление UITabBarController в качестве подчиненного объекта, кроме окна.)

Я предполагаю, что Apple предположил, что -initWithNibName: bundle: обычно не будет использоваться для создания представления корневого окна, поэтому он не корректирует рамку в вашем случае. Изменение размера его вручную, как вы это сделали, прекрасно, и на самом деле рекомендуется в "Руководство по программированию на просмотр контроллера для iPhone OS" , но вы действительно должны использовать [[UIScreen mainScreen] applicationFrame], поскольку строка состояния не всегда высока в 20 пикселей (например, она выше, когда вы находитесь на телефонном звонке.)

Ответ 2

Это намного проще и работает (iOS 4.0 и более поздние версии)

MyRootViewController *vc = [[MyRootViewController alloc] init];    
[window setRootViewController:vc];
[vc release];

-setRootViewController автоматически добавляет представление контроллера в окно, поэтому вам не нужно беспокоиться об этом. Свойство (неатомное, удержание), таким образом, освобождая его после присвоения его окну, эффективно передает владение объектом в UIWindow и будет освобождено (и, следовательно, освобождено), когда окно будет освобождено. Вы могли бы, конечно, создать переменную экземпляра и сохранить ссылку на нее и опубликовать в -dealloc, если хотите сделать что-то с ним в других методах делегирования приложения. Я предпочитаю вышеупомянутый метод, так как он автоматически заботится о очистке.

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

Вам не нужно использовать initWithNibName, просто... alloc] init]; сделаю.

Ответ 3

Я предполагаю, что ваш UITabBarController является выходом IB, поэтому, когда вызывается applicationDidFinishLaunching:, он уже инициализирован. Попробуйте следующее: сразу после создания экземпляра вашего контроллера просмотра выполните:

[vc setWantsFullScreenLayout:YES];

Ответ 4

До второго, что было сказано выше: Здесь код, который я должен был использовать:

#define MAIN_SCREEN_OFFSET_PIXELS     20

- (void) pushDownViewOnMainScreen {
  CGRect r = [[UIScreen mainScreen] applicationFrame];
  r.origin.y -= MAIN_SCREEN_OFFSET_PIXELS;

  self.view.frame = r;
}


- (void) viewDidLoad {
  [self pushDownViewOnMainScreen];

  // ...
}