Domanda

AGGIORNAMENTO:Vedi la mia risposta a questa domanda prima.Questo sembra essere un bug.Un minimo di test case è stato creato anche un rapporto è stato presentato con Apple.(Fissato iPhone OS 3.1.)

Ecco un puzzle da "io sono così vicino!" dipartimento.

Ho una Scheda di Bar-based app per iPhone.Ogni scheda dispone di un UINavigationController con i soliti sospetti (nav bar, tavola di vista ...che a sua volta può portare a un'altra VC, etc.).

Ora, uno di quelli di livello inferiore VCs è quello di essere utilizzato in verticale e modalità paesaggio.Ma c'è un problema.Il nostro paesaggio-friendly di VC shouldAutorotateToInterfaceOrientation: non avere chiamato out-of-the-box!Cosa fare?

Ecco cosa facciamo.Nel mio Tab Bar Controller, che ho implementato nel proprio file, ho questo:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
     return [self.selectedViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}

Questo finisce per propagare la richiesta per il mio paesaggio-friendly VC, che risponde a questo messaggio.Tutti i miei altri VCs non implementare questo metodo, in modo che andare semplicemente con il default orientamento verticale.

Problema risolto!!!Yay!

Bene, non del tutto. :(

Sembra che le cose non vanno così bene quando il mio paesaggio-friendly VC è richiamata dall'interno la profondità della tab bar controller MoreNavigationController.

Ho deciso di mettere a confronto/contrasto tra un VC chiamato da uno dei primi quattro scheda di bar UINavigationControllers ...e la stessa VC chiamati dall' MoreNavigationController.Questo sta per essere un po ' ultra-dettagliate, in modo da portare con me.Speriamo che il gioco da giocare si rivela utile per le indagini su una serie di cose.

Quando l'applicazione di carichi, ci sono diversi iniziale chiamate al tab bar controller shouldAutorotate...metodo.In questi primi casi, selectedViewController è pari a zero.Tuttavia, abbiamo finalmente completato il caricamento, la scheda iniziale è selezionata la voce, e tutto va bene.

Destra.Prima di tutto, bisogna scegliere uno dei primi quattro schede di bar e drill-down per il nostro VC.

Prendiamo terzo nav bar voce, in modo che il terzo nav controller.Noi di drill-down per il nostro VC che supporta la rotazione.Una rapida ispezione, conferma che il padre è infatti il terzo nav controller dal nostro tab bar controller di visualizzazione elenco.Bene!

Facciamo ruotare il dispositivo.La tab bar controller è richiesto per autorotate (vedere il codice di cui sopra).Osserviamo che selectedViewController è anche la terza nav controller, più il nav controller superiore e visibile view controller sia impostato per il nostro fidato VC che supporta la rotazione.

Così, la tab bar controller di trasmettere il shouldAutorotate messaggio, la terza nav controller ...ma il nostro punto di rotazione-friendly VC infine ottiene il messaggio.(Non sto facendo nulla di speciale qui.Forse desiderato VC ottiene il messaggio, perché è la parte superiore e/o visibile VC?) In ogni caso, ci ruota per il paesaggio, le cose si sono ridimensionate, e tutto va bene."Un Grande Successo!"

Ora andiamo a colpire il pulsante indietro e pop VC stack, lasciando la modalità paesaggio nel processo.La tab bar controller è interrogato di nuovo.

Tempo per un po ' da parte da qui.Il topViewController per il nostro nav controller è ancora quello di rotazione-friendly VC, ma visibleViewController è ora impostato per UISnapshotModalViewController!Eh.Mai visto prima ...ma Erica Sadun ha.Sembra per "scomparire view controller" (che in questo caso è certamente vero - è scomparsa bene).

Come ho tenere il passo, il visibile VC rimane come Snapshot, ma il top VC alla fine cambia per il prossimo VC sullo stack, dal momento che il mio speciale VC è alla fine è andata.Sono abbastanza fiera.

Così che lo scenario in cui tutto funziona bene.

Ora proviamo lo stesso test, solo che questa volta abbiamo intenzione di andare al MoreNavigationController (la scheda della barra dei menu) e drill-down per la stessa classe VC come prima.Nel mio caso accade per il 7 ° uno nella tab bar controller VC elenco.

Entriamo in rotazione a conoscenza VC e ...questa volta viene chiesto di ruotare direttamente!La Tab Bar Controller è non ha chiesto il permesso di ruotare a tutti.Hmm.

Un rapido controllo del genitore VC mostra è un MoreNavigationController.OK, ha senso.

Ora proviamo a ruotare il dispositivo. NULLA VIENE CHIAMATO.Nessuno dei nostri punti di interruzione colpito.Non nel nostro VC.Non nel nostro tab bar controller.(Eh?!?!)

O-kaaaay.Let's pop stack, andare nella stessa VC e cercare di ruotare di nuovo.Strano.ORA dobbiamo arrivare a una chiamata in Tab Bar Controller chiedendo la relativa autorizzazione.Qui, il Controller selezionato è il nostro fidato Nav controller (#7), ma questa volta la sua visibleViewController e topViewController sono IMPOSTATO A ZERO!

Una volta che si continua da qui, un misterioso messaggio viene visualizzato nella console di debug:

Utilizzando due fasi di rotazione di animazione.Per utilizzare il fluido singolo stadio l'animazione, questa applicazione deve rimuovere le due fasi del metodo implementazioni.

Misterioso perché Non sto a due stadi di rotazione animazione!No SecondHalf varianti del metodo sono in gioco ovunque nel mio codice sorgente.

Ahimè, il mio rotazione-conoscenza VC non è mai detto che la rotazione è in corso (anche se la rotazione non si verificano sullo schermo), quindi ovviamente il mio punto di vista è tutto rovinato come un risultato.Il caos e la tristezza che ne derivano.:(

Abbiamo vinto nemmeno la briga di schioccare la pila a questo punto.

Penso che il View Controller doc accenna al possibile problema:

Se si desidera eseguire personalizzato le animazioni durante un orientamento cambiare, è possibile farlo in uno dei due modi.Modifiche di orientamento utilizzati per si verifica in due passaggi, con le notifiche che si verificano all'inizio, nel mezzo, e la fine della rotazione.Tuttavia, in iPhone OS 3.0, il supporto è stato aggiunto per l'esecuzione di orientamento modifiche in un solo passaggio.Utilizzando un unico passaggio cambiamento di orientamento tende ad essere più veloce rispetto al vecchio processo in due fasi ed è generalmente raccomandato per tutti i nuovi codice.

Mi chiedo se MoreNavigationController risponde ancora il processo in due fasi, e quindi di intervento fino a qualsiasi tentativo di utilizzare il processo di uno stadio?Si noti che, se si risponde a due passi messaggi, ad un passo variante non funziona (ancora una volta, per la documentazione).Io non sto per rispondere, ma ho una forte sospetto qualcosa dietro le quinte È.

Infatti, se io commento singola-metodo di passaggio, e tenta di rispondere a willAnimateSecondHalfOfRotationFrominterfaceorientation:durata:, Io fare ottenere il memo!Ma ancora non pop dallo stack molto pulito (in termini di grafica).Ancora più strano: willAnimateFirstHalfOfRotationFrominterfaceorientation:durata: NON è chiamato, anche quando ho provato a sneak una chiamata a sé (utilizzando il FirstHalf messaggio) in shouldAutorotateToInterfaceOrientation:.Restituisce immediatamente in una traccia, come se non ho mai definito.Sospiro.

In modo che il play-by-play.

In sintesi, ha chiunque gestito con successo un dispositivo di rotazione per un VC richiamata dall'interno di una Tab Bar Controller MoreNavigationController?Menti indagatrici vogliono sapere!

È stato utile?

Soluzione

Apple sconsiglia la creazione di sottoclassi UITabBarController, così ho trovato un modo semplice per gestire autorotazione utilizzo di categorie, invece.Non risolve il bug con il Più...view controller, ma penso che sia più Apple-friendly in modo di ottenere il lavoro fatto (e meno sottoclassi per voi).

Per rendere ogni scheda nella mia applicazione autorotate correttamente, ho definito -shouldAutorotateToInterfaceOrientation:nel mio view controller, ma sono tutti all'interno di UINavigationControllers all'interno di un UITabBarController, in modo che il messaggio non viene inviato lungo la catena del mio VC fino a quei due anche rispondere.Così ho aggiunto le seguenti righe alla mia app delegato file:

Aggiunto al fondo di MyAppDelegate.h

@interface UITabBarController (MyApp)
@end

@interface UINavigationController (MyApp)
@end

Aggiunto al fondo di MyAppDelegate.m

@implementation UITabBarController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return YES;
}
@end

@implementation UINavigationController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return YES;
}
@end

Altri suggerimenti

Sembra che abbiamo un bug.Ho creato un riproducibili, minima prova, e viene segnalato tramite Apple Bug Reporter (RADAR Problema 7139857).

Aggiornamento:Questo problema è stato risolto come di iPhone OS 3.1.

Il problema fondamentale è:

View controller già su un Controller di navigazione stack non ricevere willAnimateRotationToInterfaceOrientation:durata: messaggi quando una Tab Bar Controller 'Più Controller di Navigazione è in utilizzare.

Questo problema non non si verifica quando la scheda di bar voce del controller di visualizzazione di base controller.Solo quando sono navigation controller e solo quando il "di Più" gerarchia di navigazione è in uso.

Il messaggio della console (su due fasi di rotazione animazione) suggerisce che qualcosa all'interno del quadro (il Più Controller di Navigazione?) ancora con due stage di animazione, anche se a singolo stadio è ora raccomandato di iPhone OS 3.0.

Che può spiegare perché willAnimateRotationToInterfaceOrientation: non viene chiamato in quel particolare caso.Per Apple vista controler documentazione, questo messaggio NON può essere invocato quando in due fasi, prima e seconda metà di orientamento messaggi a cui si è risposto, invece.

Una versione leggermente modificata di Victorb risposta che consente ad ogni singola view controller per decidere se si consente la rotazione.

Qui come gist per il semplice copia & fork

AppDelegate.h

@interface UITabBarController (MyApp)
@end

@interface UINavigationController (MyApp)
@end

AppDelegate.m

@implementation UITabBarController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    UIViewController *selectedVC = [self selectedViewController];
    if ([selectedVC respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
        return [selectedVC shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
    }

    //optimistic return - if you want no rotation, you have to specifically tell me!
    return YES;
}
@end

@implementation UINavigationController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    UIViewController *visibleVC = [self visibleViewController];
    if ([visibleVC respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
        return [visibleVC shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
    }

    //optimistic return - if you want no rotation, you have to specifically tell me!
    return YES;
}
@end
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top