2014-10-22 16 views
8

Ho trovato un piccolo cambiamento di comportamento tra 7.1 e 8 sul metodo UIViewController shouldAutorotate. Apple View Controller Programming Guide afferma che Questo metodo viene chiamato prima di eseguire qualsiasi autorotazione.shouldAutorotate il comportamento in iOS 8

Tuttavia ho notato che quando si disabilita semplicemente shouldAutorotate (return NO), il metodo viene chiamato su Portrait -> Landscape rotation, ma non sul seguente Landscape -> Portrait rotation. Ancora una volta il metodo dovrebbe essere sempre chiamato come lo capisco. Questo si verifica quando si esegue su iOS 8, ma non su iOS 7.1.

Questo sembra essere correlato a un nuovo metodo nello stack di chiamate in iOS 8:

[UIWindow shouldAutorotateToInterfaceOrientation:checkForDismissal:isRotationDisabled]

Non riuscivo a trovare C'è una descrizione di questo metodo e il suo comportamento, alcuna idea di dove potrei trovare più informazioni su questo metodo interno?

Semplici passi per riprodurre questo:

  1. Creare una nuova Visualizzazione singola progetto di applicazione in Xcode
  2. Aggiornare il ViewController.m per attuare shouldAutorotate

    - (BOOL)shouldAutorotate 
    { 
        UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; 
        NSLog(@"%s orientation is %@", __PRETTY_FUNCTION__, [self stringFromDeviceOrientation:orientation]); 
        // Disable autorotation of the interface. 
        return NO; 
    } 
    
    - (NSString *) stringFromDeviceOrientation:(UIDeviceOrientation)uido 
    { 
        NSString *orientation = @"UIDeviceOrientationUnknown"; 
        switch (uido) { 
         case UIDeviceOrientationPortrait: 
          orientation = @"Portrait"; 
          break; 
         case UIDeviceOrientationPortraitUpsideDown: 
          orientation = @"PortraitUpsideDown"; 
          break; 
         case UIDeviceOrientationLandscapeRight: 
          orientation = @"LandscapeRight"; 
          break; 
         case UIDeviceOrientationLandscapeLeft: 
          orientation = @"LandscapeLeft"; 
          break; 
         case UIDeviceOrientationFaceDown: 
          orientation = @"FaceDown"; 
          break; 
         case UIDeviceOrientationFaceUp: 
          orientation = @"FaceUp"; 
          break; 
          default: 
           break; 
         } 
         return orientation; 
        } 
    
  3. Run sul simulatore iPhone 5s (7.1): shouldAutorotate viene chiamato quando si passa a Paesaggio e torna a Ritratto

  4. Esegui su simulatore iPhone 5s (8.0) o iPhone 6: shouldAutorotate viene chiamato quando si passa a Panorama ma non viene chiamato quando si passa a Portrait.

risposta

9

La stessa cosa mi stava succedendo. Ho la sensazione che ci sia un bug in iOS8 perché il mio stesso codice ha funzionato bene su iOS7. Inoltre, proprio come utente, avevo un sacco di problemi di rotazione nelle app che uso. In 8 shouldAutorotate chiamate quando si ruota di lato ma non di nuovo quando si ritorna a una rotazione normale. Questo a meno che non abbia effettivamente effettuato un'autorotazione laterale, nel qual caso sul ritorno viene chiamato.

Quindi è perché il tuo "shouldAutorotate" restituisce sempre "NO". La mia ipotesi è che per qualche ragione in iOS8 (i programmatori di apple che hanno cambiato questo comportamento) hanno deciso che se hanno ottenuto un NO ruotando di lato, non hanno bisogno di chiamare shouldAutorotate quando ruotano di nuovo in verticale. Quindi ha rotto il comportamento che ci aspettavamo.

Nessuno ne parla o si lamenta. Google non restituisce quasi nessun risultato per questo scenario esatto. Penso che sia perché, in tal caso, devi provare a utilizzare "shouldAutorotate" come notifica di rotazione del dispositivo, ma NON utilizzare effettivamente le funzioni di rotazione automatica del sistema operativo. Ad esempio, faccio giochi opengl. Quindi, solo questo per far sapere al mio motore di ruotare la grafica del gioco. Ma non sto ruotando il mio punto di vista. Non penso che molte persone stessero usando questo per le notifiche di rotazione del dispositivo.

Quindi ho deciso di utilizzare invece le notifiche del dispositivo.A mio avviso il regolatore:

- (void) movingToBackground: (NSNotification *) notification { 
    [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; 
} 

- (void) movingToForeground: (NSNotification *) notification { 
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 
} 

e di ricevere i messaggi:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewChanging:) name:UIDeviceOrientationDidChangeNotification object:nil]; 

e il metodo:

- (void)viewChanging:(NSNotification*)notification 
{ 
    NSLog(@"View is changing"); 
    previousOrientation = orientation; 
    orientation = [[UIDevice currentDevice] orientation]; 

    if (previousOrientation==orientation && forceReorientation==NO) { 
     return; 
    } 
    ... do stuff ... 

e poi di nuovo a mio controller di vista ho girato tutta roba rotazione automatica a NO.

+1

Sono d'accordo con la tua analisi, il metodo sulla via del ritorno non è chiamato probabilmente a causa di questo nuovo 'shouldAutorotateToInterfaceOrientation' e il suo flag' isRotationDisabled'. La soluzione (usando Notifiche) è il modo corretto, e non vi è alcuna garanzia che il codice di autorotazione venga chiamato, specialmente ora che iOs 8 gestisce le rotazioni quando le dimensioni cambiano. Aspetterò un po 'prima di accettare la tua risposta, nel caso venissero a conoscenza di altre informazioni. – lazi74

+1

grazie. btw sto usando il codice sopra ora nelle mie app e sembra funzionare. La mia unica preoccupazione era che beginGeneratingDeviceOrientationNotifications potrebbe causare troppe notifiche con ogni leggera rotazione, anche se non è di 90 gradi. Ma non vedo la stampa di "Visualizza sta cambiando" tranne che sulle reali rotazioni del dispositivo. Quindi penso che sia buono. – badweasel

+0

Stai avendo la soluzione? Faccio il controllo di rotazione meraviglioso della barra di stato. Eppure ha raggiunto una navigazione con protocollo url coordinato con l'accelerometro da un'altra app o il ritorno da un altro orientamento. Purtroppo, si è fermato sul passaggio in cui la tastiera su schermo dovrebbe ruotare di conseguenza. Nella mia soluzione, ho (come te) una vista fissa con orientamento verticale con il suo strato OpenGL. Come forzare iOS a NON animare la sua rotazione orribile ??? :-) –

Problemi correlati