2014-09-24 14 views
8

Sto costruendo un'applicazione complessa con una specie di ramo nel mezzo.L'eliminazione di un ViewController più in basso nello stack non si comporta come previsto

Ad un certo punto nell'app viene presentato un particolare UIViewController, lo chiameremo mainViewController (abbreviato mainVC).

Il mainVC presenta un altro controller di vista, per codice, utilizzando il seguente codice (spoglierò su parti di esso per motivi di privacy):

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"SecondaryStoryboard" bundle:secondaryBundle]; 
SecondViewController *secondVC = [storyboard instantiateInitialViewController]; 
[self presentViewController:secondVC animated:YES completion:nil]; 

Così il secondVC sarà successivamente presentato un altro controllore vista, chiamato thirdVC. Questo viene fatto utilizzando un segue personalizzato, impostare nello storyboard utilizzato nel codice di cui sopra, che il codice simile al seguente:

@implementation VCCustomPushSegue 

- (void)perform { 

    UIView *sourceView = ((UIViewController *)self.sourceViewController).view; 
    UIView *destinationView = ((UIViewController *)self.destinationViewController).view; 

    UIWindow *window = [[[UIApplication sharedApplication] delegate] window]; 
    destinationView.center = CGPointMake(sourceView.center.x + sourceView.frame.size.width, destinationView.center.y); 

    [window insertSubview:destinationView aboveSubview:sourceView]; 

    [UIView animateWithDuration:0.4 
        animations:^{ 
         destinationView.center = CGPointMake(sourceView.center.x, destinationView.center.y); 
         sourceView.center = CGPointMake(0 - sourceView.center.x, destinationView.center.y); 
        } 
        completion:^(BOOL finished){ 

         [self.sourceViewController presentViewController:self.destinationViewController animated:NO completion:nil]; 
        }]; 

} 

@end 

Come si può vedere questo segue presenta il modale vista di destinazione del controller (mediante l'uso di presentViewController:) con un'animazione personalizzata (una diapositiva da destra a sinistra).

Quindi praticamente fino a qui è tutto a posto. Presento lo secondVC con un'animazione modale classica (fa scorrere verso l'alto dal basso) e presenta lo thirdVC con la mia transizione personalizzata.

Ma quando voglio eliminare lo thirdVC, quello che voglio è tornare direttamente allo mainVC. Così ho chiamare il seguente dalla thirdVC:

self.modalTransitionStyle = UIModalTransitionStyleCoverVertical; 
[self.presentingViewController.presentingViewController dismissViewControllerAnimated:_animate completion:nil]; 

In questo modo, sto chiamando dismissViewControllerAnimated: direttamente sul mainVC (a cui fa riferimento self.presentingViewController.presentingViewController), e mi aspetto il thirdVC essere respinto con un'animazione, e il secondVC sparire semplicemente senza animazione.

Come Apple dice nella documentazione UIViewController Classe:

La presentazione controller di vista è responsabile per respingere il controller della vista ha presentato. Se si chiama questo metodo sul controller della vista presentata , esso inoltra automaticamente il messaggio al controller di visualizzazione presentatore .

Se si presentano diversi controller di vista in successione, costruendo così una pila di controller di vista presentati, chiamata a questo metodo su un controller di vista inferiore nello stack respinge il suo immediato Bambini controller e tutti i controller di vista di cui sopra quel bambino in pila. Quando ciò accade, solo la vista più in alto viene ignorata in una modalità animata ; qualsiasi controller di vista intermedio viene semplicemente rimosso dallo stack . La vista più in alto viene ignorata utilizzando lo stile di transizione modale , che può differire dagli stili utilizzati da altri controller di vista inferiori nello stack.

Il problema è che non è quello che succede.Nel mio scenario, lo thirdVC scompare e mostra lo secondVC che viene rimosso con l'animazione modale della diapositiva in basso.

Cosa sto sbagliando?


Edit:

Così @ risposta di codeFi è probabilmente lavorando in un progetto classico, ma il problema qui è che sto lavorando su un quadro. Quindi mainVC si trova in un'app client e lo secondVC e thirdVC sono nel mio framework, in uno storyboard separato. Non ho accesso a mainVC in alcun modo diverso da un riferimento ad esso nel mio codice, quindi i segui di svolgimento non sono purtroppo un'opzione qui.

+1

Questo cambiamento di comportamento si è verificato con iOS 8, in 7 ha funzionato correttamente. Sto cercando di aggirare il problema ora. – theLastNightTrain

+0

@theLastNightTrain: beh sei corretto, succede solo su iOS 8 .. Fammi sapere se trovi qualcosa dalla tua parte .. – rdurand

+0

@theLastNightTrain: Qualche aggiornamento? Sarei lieto di offrire una taglia per una risposta per risolvere questo problema .. – rdurand

risposta

2

ho avuto questo esattamente lo stesso problema, e sono riuscito a lavorare visivamente attorno ad esso aggiungendo un'istantanea dello schermo come sottoview a secondVC.view, in questo modo:

if (self.presentedViewController.presentedViewController) { 
    [self.presentedViewController.view addSubview:[[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO]]; 
} 

[self dismissViewControllerAnimated:YES completion:nil]; 

Non carino, ma sembra funzionare.

NOTA: se il vostro secondVC ha una barra di navigazione, è necessario nascondere la barra di navigazione tra snapshotting lo schermo e aggiungendo l'istantanea come una visualizzazione secondaria per secondVC, altrimenti apparirà l'istantanea sotto la barra di navigazione, quindi apparentemente mostra una doppia barra di navigazione durante l'animazione di licenziamento.Codice:

if (self.presentedViewController.presentedViewController) { 
    UIView *snapshot = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO]; 
    [self.presentedViewController.navigationController setNavigationBarHidden:YES animated:NO]; 
    [self.presentedViewController.view addSubview:snapshot]; 
} 

[self dismissViewControllerAnimated:YES completion:nil]; 
+0

Grazie, lo proverò e ti farò sapere come funziona. – rdurand

+1

Sembra funzionare abbastanza bene .. Andrà bene fino a quando non lo risolvono. Grazie ! – rdurand

+0

Si noti che se il 'secondVC' ha una barra di navigazione, sarà necessario nascondere la barra di navigazione tra l'acquisizione istantanea dello schermo e l'aggiunta dell'istantanea come sottoview a' secondVC', altrimenti l'istantanea apparirà sotto la barra di navigazione, quindi apparentemente mostra una doppia barra di navigazione durante l'animazione di licenziamento. – rhelba

1

Ho avuto lo stesso problema e l'ho risolto utilizzando UnwindSegues.

Fondamentalmente, tutto ciò che devi fare è aggiungere un metodo Segue Unwind IBAction nel ViewController che vuoi seguire e poi connettere in IB l'azione Exit al metodo Unwind Segue.

Esempio:

Diciamo che avete tre ViewControllers (VC1, VC2, VC3) e si vuole andare da VC3 a VC1.

Fase 1 aggiungere un metodo per VC1 simile al seguente:

- (IBAction)unwindToVC1:(UIStoryboardSegue*)sender 
{ 
} 

Fase 2 Go in Interface Builder per VC3 e selezionarlo. Quindi trascina CTRL dall'icona VC all'icona Exit e seleziona il metodo che hai appena aggiunto in VC1.

Add Unwind Segue

Fase 3 Mentre era ancora in IB e con VC3 selezionato, selezionare il proprio Rilassatevi Segue e nelle Impostazioni Attributi aggiungere un Segue Identifier.

enter image description here enter image description here

Fase 4 Vai VC3 in cui è necessario eseguire la segue (o respingere il VC) e aggiungere il seguente:

[self performSegueWithIdentifier:@"VC1Segue" sender:self]; 
+0

Ehi! Grazie per la tua risposta. Ho usato svolgersi in passato, ma in questo caso non sono un'opzione. Qualcosa che non ho menzionato per mantenere la domanda "semplice" è che la seconda e la terza visione dei controller sono all'interno di un framework. Quindi in pratica il mainVC si trova nell'app di un cliente, e gli altri due sono separati da esso, nel framework (da qui l'altro storyboard). Scusa per non aver detto questa mia domanda :) – rdurand

Problemi correlati