Offset on UIWindow addSubview

Eu tenho um aplicativo baseado em UITabBar que funciona muito bem. Sob certas circunstâncias, estou mostrando um UIViewController diferente. Agora o que me incomoda é que eu tenho que ajustar o quadro para a ponta de teste (e apenas a ponta de teste!) Para exibir corretamente. (Caso contrário, a visualização está abaixo da barra de status).

- (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]; } 

Então, talvez algo esteja errado com o bico de teste? Não pode ser. A ponta de teste funciona como desejado em um novo projeto limpo. E um novo bico limpo mostra os mesmos sintomas. Então, algo deve estar errado com o bico MainWindow, certo? Mas o UITabBarController exibe muito bem.

Estou um pouco confuso e ficando sem ideias aqui. Alguma sugestão de como rastrear isso?

Adicionar a visualização raiz à sua interface do usuário pode ser complicado, pois a janela sempre se sobrepõe à barra de status. O quadro de sua visualização raiz deve, portanto, ser redefinido para [[UIScreen mainScreen] applicationFrame] para evitar que ele se sobreponha à barra de status também. Nós normalmente não temos que nos preocupar com isso, porque o UIViewController modifica o quadro para nós … exceto quando isso não acontece. Aqui está o acordo:

  • Se você criar seu controlador de visualização e sua visualização no mesmo NIB e aninhar a visualização sob o controlador de exibição, ele ajustará o quadro da exibição automaticamente.
  • Se você criar seu controlador de visualização e sua visualização no mesmo NIB, mas conectar a visualização ao controlador de exibição pela saída de exibição do controlador, em vez de aninhá-lo, o controlador não ajustará o quadro da exibição automaticamente.
  • Se você criar seu view controller em um NIB e conectá-lo a uma view definida em um NIB desanexado definindo a propriedade “NIB Name” do controlador view no IB, ele ajustará o frame da view automaticamente, mas somente se você também tiver ” Redimensionar vista do NIB “verificado.
  • Se você criar seu controlador de visualização chamando -initWithNibName: bundle :, ele não ajustará o quadro da exibição automaticamente.
  • O UITabBarController espera que sua visão seja adicionada como a visualização raiz da janela e, portanto, sempre ajusta o quadro de sua própria visualização para corresponder ao quadro do aplicativo automaticamente. (Como resultado, você notará uma diferença estranha de 20 pixels se você adicionar a visualização de um UITabBarController como uma subvisualização de algo diferente da janela.)

Eu acho que a Apple imaginou que -initWithNibName: bundle: normalmente não seria usado para criar a visão raiz da janela, então ela não ajusta o quadro no seu caso. Redimensioná-lo manualmente como você fez é bom, e é de fato recomendado no View Controller Programming Guide para iPhone OS , mas você deve realmente usar [[UIScreen mainScreen] applicationFrame] já que a barra de status nem sempre tem 20 pixels de altura é mais alto quando você está em uma chamada telefônica.)

Isso é muito mais simples e também funciona (iOS 4.0 e posterior)

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

-setRootViewController adiciona automaticamente a visão do controlador à janela para que você não precise se preocupar com isso. A propriedade é (nonatomic, reter), portanto liberá-la depois de atribuí-la à janela efetivamente entrega a propriedade do object para a UIWindow e será liberada (e consequentemente desalocada) quando a janela for desalocada. É claro que você poderia criar uma variável de instância e manter uma referência a ela e liberar-se em -dealloc se quiser fazer coisas com ela nos outros methods de delegação do aplicativo. Eu prefiro o método acima, pois cuida da limpeza automaticamente.

Caso você não saiba, você também pode liberar os controladores de visualização imediatamente após adicionar suas visualizações a qualquer outra visualização como uma subvisualização ou apresentar uma visualização de controladores de visualização restrita. Sempre que uma visão é removida ou removida da pilha de visualizações, seus controladores correspondentes também serão liberados.

Você não precisa usar initWithNibName, apenas … alloc] init]; vai fazer.

Estou assumindo que o seu UITabBarController é uma saída do IB, para que quando applicationDidFinishLaunching: é chamado, ele já esteja inicializado. Tente o seguinte: logo após instanciar seu controlador de visualização, faça:

 [vc setWantsFullScreenLayout:YES]; 

Apenas para finalizar o que foi dito acima: Aqui está o código que eu tive que usar:

 #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]; // ... }