Perché devo impostare manualmente il frame della mia vista in viewDidLoad?

Ho una configurazione piuttosto semplice con un UINavigationController all’interno di un UITabBarController. Sto volendo impostare la vista del rootViewController di quel controller, ma quando guardo self.view.frame all’interno di viewDidLoad, ottengo questo (in orizzontale , per esempio):

1. view frame: {{20, 0}, {748, 1024}} // looks like an odd portrait mode 

Quindi eseguo l’autorotazione su Portrait e ottengo questo:

 2. view frame: {{0, 0}, {768, 911}} 

Poi quando torno a Landscape, il frame è ora questo:

 3. view frame: {{0, 0}, {1024, 655}} 

E altri eventi di autorotazione si invertiranno tra i valori di frame # 2 e # 3.

Per aggirare la stranezza di # 1, sto facendo questo in viewDidLoad:

     if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) { self.view.frame = CGRectMake(0, 0, 768, 911); } else { self.view.frame = CGRectMake(0, 0, 1024, 655); } 

    Mi sento come se mi mancasse ovviamente qualcosa qui. Perché il frame predefinito della vista non corrisponde alla cornice quando si ritorna automaticamente allo stesso orientamento? La cornice della vista non viene impostata sull’orientamento iniziale? Molto confuso…

    Devo dire che nessuno dei precedenti, incluso il mio trucco kludgy, cambia visivamente qualcosa. La ragione per cui ho l’hack è che quando eseguo il layout delle mie visualizzazioni secondarie in questa vista, saranno basate su dove mi aspetto che sia, ovvero l’angolo in alto a sinistra appena sotto la barra di navigazione.

    Che cosa sto facendo di sbagliato?

    AGGIORNAMENTO: distriggersndo tutte le cose di autosizing sulla vista, il risultato # 1 deve essere:

     view frame: {{0, 0}, {748, 1024}} 

    Sembra un po ‘più vicino, ma non corrisponde ancora al # 3.

    Non è garantito che il frame sia lo stesso in viewDidLoad come lo sarà quando verrà visualizzata la vista. UIKit regola il frame della vista del controller di visualizzazione prima di visualizzarlo, in base al contesto in cui apparirà. La dimensione viene determinata in base all’orientamento dell’interfaccia e alle dimensioni di qualsiasi barra di navigazione visibile, barra delle tabs, barra degli strumenti o barra di stato (che a sua volta ha un’altezza che può cambiare, ad esempio quando si è impegnati in una telefonata).

    Aiuta a capire cosa succede quando viene caricata e visualizzata la vista di un controller di visualizzazione:

    1. Qualcosa accede per la prima volta alla proprietà della view del controller della view . Ciò potrebbe verificarsi nel tuo codice o in UIKit in risposta a un’azione dell’utente come selezionare una scheda.

    2. UIKit lazy-carica la vista del controller di visualizzazione chiamando loadView se è definito o caricando la vista dal NIB specificato in initWithNibName:bundle: Se nessuno dei due esiste, UIKit carica solo una vista vuota.

    3. UIKit chiama viewDidLoad una volta che la vista e le sue sottoview sono state completamente caricate. A questo punto il frame della vista sarà qualsiasi cosa sia stato impostato in NIB o in loadView .

    4. Qualcosa chiede a UIKit di mostrare la vista del tuo controller di visualizzazione. Anche in questo caso, questa può essere un’azione dell’utente come toccare una scheda o una chiamata al metodo esplicita nel codice come pushViewController:animated: or presentModalViewController:animated:

    5. UIKit ridimensiona la vista in base al contesto in cui verrà presentata, come descritto sopra.

    6. UIKit chiama viewWillAppear: La cornice ora dovrebbe essere la dimensione che verrà visualizzata. (?) EDIT: questo potrebbe non essere più vero. Vedi i commenti qui sotto.

    7. UIKit mostra la vista, con o senza animazioni.

    8. UIKit chiama viewDidAppear:

    Come puoi vedere, se hai bisogno di conoscere la dimensione della cornice della tua vista prima che venga presentata, viewWillAppear: è la tua unica e unica opportunità. Ricorda che questa dimensione può cambiare dopo che la visualizzazione viene visualizzata per vari motivi, inclusi eventi di rotazione o modifiche nell’altezza della barra di stato. Per questo motivo, è importante assegnare ad ogni sottoview un’appropriata maschera di autoresizzazione, per garantire che il layout possa adattarsi correttamente per eventuali cambiamenti di limiti.

    Se desideri creare manualmente la gerarchia della vista, la posizione consigliata per farlo è in loadView. Dal momento che costruisci la vista tu stesso con questo metodo, puoi inizializzare la sua cornice con qualsiasi cosa desideri. La taglia che scegli non ha molta importanza, dal momento che UIKit probabilmente lo cambierà comunque. Assicurati di impostare i tuoi autoresizingMasks in modo appropriato.

    Ci sarà un metodo nella tua class

     - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return YES; } 

    Metti la cornice in questo metodo … Allora funzionerà bene.

    Per esempio:

     - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations if(interfaceOrientation == UIDeviceOrientationPortrait || UIDeviceOrientationPortraitUpsideDown) self.view.frame = CGRectMake(0, 0, FRAME.WIDTHinPOTRAIT, FRAME.HEIGHTinPOTRAIT); else if(interfaceOrientation == UIDeviceOrientationLandscapeRight || UIDeviceOrientationLandscapeLeft) self.view.frame = CGRectMake(0, 0, FRAME.WIDTHinLANDSCAPE, FRAME.HEIGHTinLANDSCAPE); return YES; } 

    FRAME.WIDTH> larghezza desiderata FRAME.HEIGHT> altezza desiderata