Смещение на UIWindow addSubview - PullRequest
       16

Смещение на UIWindow addSubview

26 голосов
/ 11 февраля 2010

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

- (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 отображает просто отлично.

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

Ответы [ 4 ]

76 голосов
/ 15 апреля 2010

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

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

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

4 голосов
/ 09 апреля 2011

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

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

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

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

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

0 голосов
/ 04 ноября 2010

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

#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];

  // ...
}
0 голосов
/ 12 февраля 2010

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

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