2010-02-11 3 views
26

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

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

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

ответ

76

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

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

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

+3

Я бы дважды повысил, если бы мог :) –

+1

окончательный ответ на один из самых раздражающих общих причуд в развитии iOS. 5 звезд, 10/10, снова сыграл бы –

+0

не читал весь ваш ответ, но я очень доволен ключевыми словами [[UIScreen mainScreen] applicationFrame] –

0

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

[vc setWantsFullScreenLayout:YES]; 
+0

После этого 20 пикселов в нижней части экрана (которые были белыми, а не цвет фона) исчезают, и вся область покрыта. Но элементы управления пользовательского интерфейса все еще находятся на 20 пикселях слишком близко к вершине. Поэтому я думаю, что это просто изменяет размер изображения с 320x460 до 320x480. Происхождение все еще не так. И в конце концов это будет просто обход. Я хотел бы найти причину этого. – tcurdt

0

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

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

    // ... 
} 
4

Это гораздо проще, а также работает (IOS 4.0 и выше)

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

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

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

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

+0

Вам нужно использовать initWithNibName, если вы загружаете из наконечника, хотя , ofc ... – fnf

Смежные вопросы