2010-02-11 18 views
26

Tengo una aplicación basada en UITabBar que funciona muy bien. Sin embargo, bajo ciertas circunstancias, estoy mostrando un UIViewController diferente. Ahora lo que me molesta es que tengo que ajustar el marco para la punta de prueba (y solo la punta de prueba!) Para que se muestre correctamente. (De lo contrario, la vista está debajo de la barra de estado).Offset en 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]; 
} 

Entonces, ¿hay algún problema con la punta de prueba? No puede ser El plumón de prueba funciona como se desea en un nuevo proyecto limpio. Y una nueva punta limpia muestra los mismos síntomas. Entonces algo debe estar mal con la plumilla MainWindow, ¿verdad? Pero el UITabBarController se muestra bien.

Estoy un poco confundido y me estoy quedando sin ideas aquí. ¿Alguna sugerencia de cómo rastrear esto?

Respuesta

76

Adición de la vista raíz de su UIWindow puede ser complicado ya que la ventana siempre se solapa por debajo de la barra de estado. Por lo tanto, el marco de la vista raíz debe restablecerse a [[UIScreen mainScreen] applicationFrame] para evitar que también se solape con la barra de estado. Normalmente no tenemos que preocuparnos por esto porque UIViewController modifica el marco para nosotros ... excepto cuando no lo hace. Este es el trato:

  • Si crea su controlador de vista y su visión de la misma SEMILLA, y nido de la vista debajo del controlador de vista , que se ajustar el marco de la vista de forma automática.
  • Si crea su controlador de vista y su punto de vista en el mismo SEMILLA, pero conectan la vista al controlador de vista través de la salida vista del controlador lugar de anidación de ella, el controlador no ajustar el marco de la vista automáticamente.
  • Si crea su controlador de vista en una punta, y lo conecta a una vista definida en una SEMILLA individual estableciendo la propiedad "SEMILLA Nombre" del controlador de vista de IB, que se ajustar el marco de la vista de forma automática, pero solo si también tiene marcada la opción "Redimensionar vista desde NIB".
  • Si crea su controlador de vista llamando a -initWithNibName: paquete :, no ajustará el marco de la vista automáticamente.
  • UITabBarController espera que su vista se agregue como la vista raíz de la ventana y, por lo tanto, siempre ajusta el propio marco de la vista para que coincida automáticamente con el marco de la aplicación. (Como resultado, usted notará una extraña brecha de 20 píxeles si alguna vez agrega vista de un UITabBarController como subvista de que no sea la ventana de nada.)

supongo de Apple pensó que -initWithNibName: bulto: ¿no normalmente se utiliza para crear la vista raíz de la ventana, por lo que no ajusta el marco en su caso.Cambiar el tamaño manualmente como lo ha hecho está bien, y de hecho se recomienda en el View Controller Programming Guide for iPhone OS, pero realmente debería usar [[UIScreen mainScreen] applicationFrame] ya que la barra de estado no es siempre 20 píxeles de alto (por ejemplo, es más alto cuando está en una llamada telefónica .)

+3

Recompensaría dos veces si pudiera :) –

+1

la respuesta definitiva a una de las rarezas comunes más molestas en el desarrollo de iOS. 5 estrellas, 10/10, volvería a jugar –

+0

No leo toda tu respuesta, pero estoy muy contento con la palabra clave [[UIScreen mainScreen] applicationFrame] –

0

Supongo que su UITabBarController es una toma de IB, por lo que cuando se llama a applicationDidFinishLaunching:, ya está inicializado. Pruebe lo siguiente: justo después de crear instancias de su controlador de vista, hacer:

[vc setWantsFullScreenLayout:YES]; 
+0

Después de llamar a esto, los 20 píxeles en la parte inferior de la pantalla (que eran blancos y no el color de fondo de la vista) desaparecen y toda el área queda cubierta. Pero los controles de la interfaz de usuario aún son 20 píxeles demasiado cerca de la parte superior. Así que creo que esto solo cambia el tamaño de la vista de 320x460 a 320x480. El origen aún está mal. Y después de todo esto también sería solo una solución temporal. Me gustaría encontrar la causa de esto. – tcurdt

0

Sólo al segundo lo que se dijo anteriormente: Aquí está el código que tenía que utilizar:

#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

Esto es mucho más simple y también trabaja (iOS 4.0 y posterior)

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

- setRootViewContro Ller automáticamente agrega la vista del controlador a la ventana para que no tenga que preocuparse por ello. La propiedad es (no atómica, retener) por lo que su liberación después de asignarla a la ventana transfiere de forma efectiva la propiedad del objeto a la ventana UI y se liberará (y consecuentemente se desasignará) cuando la ventana se desasigna. Por supuesto, puede crear una variable de instancia y mantener una referencia a ella y liberarla en -dealloc si desea hacer cosas con ella en los demás métodos de delegado de la aplicación. Prefiero el método anterior ya que se encarga de la limpieza de forma automática.

En caso de que no lo sepa, también puede liberar los controladores de vista inmediatamente después de agregar sus vistas a cualquier otra vista como subvista o presentar una vista de controladores de vista modal. Cada vez que se quita o quita una vista de la pila de vista, también se liberarán sus controladores correspondientes.

No necesita usar initWithNibName, solo ... alloc] init]; va a hacer

+0

Debes usar initWithNibName si estás cargando desde una punta, aunque , De c... – fnf