2014-12-14 14 views
5

Mi rendo conto che lo standard didRotateFromInterfaceOrientation è obsoleto in iOS 8; tuttavia, ho un'app che deve rimanere compatibile con iOS7. Il problema che sto avendo è che quando il dispositivo viene ruotato (iPad in questo caso) questo metodo viene chiamato due volte. Questo accade su un dispositivo reale e con il simulatore. Ho semplicemente inserito un NSLog nel metodo per mostrarlo.didRotateFromInterfaceOrientation accensione due volte con rotazione

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 
{ 

     NSLog(@"didRotateCalled"); 
} 

Inoltre ho controllato il willRotateToInterfaceOrientation ma che uno funziona correttamente solo sempre chiamato una volta.

Qualche idea sul motivo per cui il metodo didRotateFromInterfaceOrientation viene sparato due volte a rotazione?

Come aggiornamento rapido. Ho inserito un breakpoint in cui ho rivelato qualcosa di interessante. Questa vista è una UISplitviewcontroller e sembra che il metodo sia chiamato prima per UISplitviewcontroller e quindi come UIViewController. Non so perché ...

Alcune informazioni aggiuntive. Sto usando Storyboard uno per iPhone e l'altro iPad. L'iPhone non usa lo splitViewController. La base di codice è condiviso così nel prepareForSegue faccio la seguente:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 
{ 
      UISplitViewController *splitViewController = (UISplitViewController *)self.view.window.rootViewController; 
      splitViewController.delegate = segue.destinationViewController; 
} 
+0

Stampa "da InterfacciaOrientazione". Che cosa ottieni? –

+1

elenca le classi ViewController che stai utilizzando e dove hai implementato 'didRotateFromInterfaceOrientation'.Potrebbe essere il tuo metodo è chiamato da diverse istanze o dal codice in classe e superclasse. – Christian

+0

Master split è un UITableViewController e la parte detail è un UIViewController. Quando una cella è selezionata sul lato master, il dettaglio viene "sostituito" con il contenuto appropriato. Puoi vedere nel mio codice sopra l'installazione per quello in preare ForSegue. – C6Silver

risposta

3

io ho la mia risposta. Ho appena scaricato i simulatori per iOS 7.1 da utilizzare nell'ultimo Xcode. Ho trovato che il metodo viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator NON viene chiamato quando è in esecuzione in iOS 7.1. Tuttavia, ho anche riscontrato che il problema che ho descritto con l'attivazione della rotazione due volte NON si verifica con il metodo willRotateToInterfaceOrientation in iOS7 ma ancora lo fa in iOS 8. Questo è un chiaro bug in Apple.

Sembra che avrò bisogno di rilevare la versione del sistema operativo che il cliente è in esecuzione e, se è iOS 8 o superiore, non eseguirò alcun codice nel metodo willRotateToInterfaceOrientation. Posso comunque lasciare il metodo viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator per i dispositivi iOS 8 poiché questo metodo verrà semplicemente ignorato da iOS 7.

Non so se questo è solo un problema per splitviewcontrollers o per tutti i metodi di visualizzazione che utilizzano la rotazione tra iOS 7 e 8. Se la tua app non sovrascrive questo metodo di quanto tu non possa mai sapere. Se è così, dovrai affrontare quello che ho fatto sopra. Non bene.

Ecco il codice che sto usando per verificare la presenza di versione:

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 
{ 
    if (NSFoundationVersionNumber == NSFoundationVersionNumber_iOS_7_1) // use this only for iOS7 devices as otherwise this fires twice under iOS8 
    { 
     ... 
    } 
} 

ho lasciato -(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator metodo come questo viene semplicemente ignorato da iOS 7 dispositivi, ma sarà chiamato da iOS 8.xe presumibilmente sopra .

1

Ho lo stesso problema (anche se nel mio caso willRotate viene eseguito due volte anche su iOS 8). Ho usato la seguente soluzione:

BOOL _willRotate; // iVar for the state 

// Methods that should be called from willRotate/didRotate (can be inline) 
- (BOOL)workaroundIOS8RotationMethodsCalledTwice_forWillRotate_shouldExecute 
{ 
    if(_willRotate) { 
     return NO; 
    } 
    _willRotate = YES; 
    return YES; 
} 

- (BOOL)workaroundIOS8RotationMethodsCalledTwice_forDidRotate_shouldExecute 
{ 
    if(_willRotate) { 
     _willRotate = NO; 
     return YES; 
    } 
    return NO; 
} 

// Inside willRotate (return if shouldn't execute): 
if(![self workaroundIOS8RotationMethodsCalledTwice_forWillRotate_shouldExecute]) { 
    return; 
} 

// Inside didRotate (return if shouldn't execute): 
if(![self workaroundIOS8RotationMethodsCalledTwice_forDidRotate_shouldExecute]) { 
    return; 
} 
0

ho trovato viewWillTransition chiamato due volte contro diversi UIViewController istanze. Alla prima chiamata, self è un'istanza valida. Ma in seconda chiamata, il sé non è valido. viewDidLoad() non viene chiamato su questa istanza non valida. Aggiungo un membro e imposta il valore su viewDidLoad, quindi controllo se self è valido o meno.

class MyViewControler: UIViewController { 
    var last_width:CGFloat? 

    override func viewDidLoad() { 
    super.viewDidLoad() 
    print(" viewDidLoad self \(self) has address: \(Unmanaged.passUnretained(self).toOpaque())") 
    last_width = self.view.bounds.width 
    } 

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { 
    print(" viewWillTransition self \(self) has address: \(Unmanaged.passUnretained(self).toOpaque())") 
    // Bug? viewWillTransition called twice with diffent self instance, ignore second call 
    if (last_width == nil || last_width == size.width) { 
     return 
    } 
    last_width = size.width 
    } 
}