2010-07-12 14 views
20

Quindi avere uno stack con tre controller di visualizzazione in cui A è root, B è il primo controller di visualizzazione modale e C è il terzo modale vc. Mi piacerebbe andare da C ad A contemporaneamente. Ho provato this solution to dismiss. Fa lavoro ma non in un modo corretto. Quello è quando l'ultimo controllore di vista è licenziato, mostrerà breifly il secondo controller di visualizzazione prima che venga mostrato il primo. Quello che sto cercando è un modo per andare dal terzo videoregistratore al primo in una bella animazione senza notare la seconda vista. Qualsiasi aiuto su questo è molto apprezzato.Eliminare più controller di visualizzazione modali contemporaneamente?

+0

Un modo più generico per ignorare di più un controller di visualizzazione modale è [qui] (https://stackoverflow.com/a/44583711/1151916) – Ramis

risposta

20

Assicurati di chiamare solo dismissModalViewControllerAnimated: una volta.

Ho scoperto che chiedendo di eliminare ogni controller modale della vista impilata farà sì che entrambi animino.

si dispone di: A =modal> B =modal> C

Si dovrebbe chiamare solo [myViewControllerA dismissModalViewControllerAnimated:YES]

Se si utilizza [myViewControllerB dismissModalViewControllerAnimated:YES], sarà respingere C, e non B. In normali (unstacked) uso, sarebbe respingere B (a causa della catena di risposta che ribolle il messaggio fino a A). Nello scenario impilato che descrivi B è un controller di visualizzazione genitore e questo ha la precedenza su un controller di visualizzazione modale.

+7

Bene come ora uso: [[[auto parentViewController] parentViewController] dismissModalViewControllerAnimated: YES]; Questo userebbe il viewcontroller root. Tuttavia, mostra ancora la seconda vc per un secondo breif. – sebrock

+0

Oh, e dovrei dire che uso il modello Utility e il secondo videoregistratore è la vista a rovescio della medaglia. Il terzo è un modale vc istanziato dal rovescio della medaglia. – sebrock

+1

NOTA: in iOS5 questo è cambiato in "presentandoViewController" http://game4mob.com/index.php/jawbreaker/66-dismiss-modal-view-in-ios5-sdk –

-5

Quello che si desidera utilizzare è popToRootViewControllerAnimated:. Ti porta al controller principale senza mostrare tutti quelli che intervengono.

+1

Questa è un'ottima soluzione se A è la radice di un 'UINavigationController' – ohhorob

+1

Oh sì. Mi sono appena svegliato, quindi non l'ho capito. – lucius

0

È possibile ignorare questi modalViewControllers sul rootViewController.

UIViewController *viewController = yourRootViewController; 

    NSMutableArray *array = [NSMutableArray array]; 
    while (viewController.modalViewController) { 
     [array addObject:viewController]; 
     viewController = viewController.modalViewController; 
    } 

    for (int i = 0; i < array.count; i++) { 
     UIViewController *viewController = array[array.count-1-i]; 
     [viewController dismissModalViewControllerAnimated:NO]; 
    } 
3

Anche se la risposta accettata ha funzionato per me, può essere superata la società e ha lasciato un animazione cercando strano dove il modale più in alto avrebbe immediatamente scompare e l'animazione sarebbe sul modalview posteriore. Ho provato molte cose per evitarlo e ho dovuto usare un po 'di trucco per farlo sembrare bello. Nota: (testato solo in iOS 8 +, ma dovrebbe funzionare iOS7 +)

In sostanza, viewControllerA crea un UINavigationController con viewControllerB come rootview e lo presenta modale.

// ViewControllerA.m 
- (void)presentViewB { 
    ViewControllerB *viewControllerB = [[ViewControllerB alloc] init]; 
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewControllerB]; 

    navigationController.modalPresentationStyle = UIModalPresentationFormSheet; 
    [self presentViewController:navigationController animated:YES completion:nil]; 
} 

Ora in viewControllerB ci accingiamo a presentare viewControllerC allo stesso modo, ma dopo lo presentiamo, ci accingiamo a mettere una fotografia istantanea del viewControllerC sopra lo strato di vista sul controller di navigazione viewControllerB s'. Quindi, quando viewControllerC scompare durante il licenziamento, non vedremo la modifica e l'animazione apparirà bella.

//ViewControllerB.m 
- (void)presentViewC { 
    ViewControllerC *viewControllerC = [[ViewControllerC alloc] init]; 

    // Custom presenter method to handle setting up dismiss and snapshotting 
    // I use this in a menu that can present many VC's so I centralized this part. 
    [self presentViewControllerForModalDismissal:viewControllerC]; 
} 

Qui di seguito sono le mie funzioni di aiuto che vengono utilizzati per presentare la vista e gestire il licenziamento. Una cosa da notare, sto usando Purelayout per aggiungere vincoli di layout automatico. È possibile modificare questo per aggiungere manualmente o ottenere Purelayout a https://github.com/PureLayout/PureLayout

#pragma mark - Modal Presentation Helper functions 
- (void)presentViewControllerForModalDismissal:(UIViewController*)viewControllerToPresent { 
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewControllerToPresent]; 
    navigationController.modalPresentationStyle = UIModalPresentationFormSheet; 

    // Ensure that anything we are trying to present with this method has a dismissBlock since I don't want to force everything to inherit from some base class. 
    NSAssert([viewControllerToPresent respondsToSelector:NSSelectorFromString(@"dismissBlock")], @"ViewControllers presented through this function must have a dismissBlock property of type (void)(^)()"); 
    [viewControllerToPresent setValue:[self getDismissalBlock] forKey:@"dismissBlock"]; 

    [self presentViewController:navigationController animated:YES completion:^{ 
     // We want the presented view and this modal menu to dismiss simultaneous. The animation looks weird and immediately becomes the menu again when dismissing. 
     // So we are snapshotting the presented view and adding it as a subview so you won't see the menu again when dismissing. 
     UIView *snapshot = [navigationController.view snapshotViewAfterScreenUpdates:NO]; 
     [self.navigationController.view addSubview:snapshot]; 
     [snapshot autoPinEdgesToSuperviewEdges]; 
    }]; 
} 

- (void(^)()) getDismissalBlock { 
    __weak __typeof(self) weakSelf = self; 
    void(^dismissBlock)() = ^{ 
     __typeof(self) blockSafeSelf = weakSelf; 
     [blockSafeSelf.navigationController.presentingViewController dismissViewControllerAnimated:YES completion:nil]; 
    }; 

    return dismissBlock; 
} 

Ora abbiamo solo bisogno per assicurarci di avere la dismissBlock definito come una proprietà in ViewControllerC.h (ovviamente è possibile sostituire tutta questa parte con metodi delegato o altri modelli di progettazione altrettanto entusiasmanti, la parte importante è quello di gestire il licenziamento a livello viewControllerB)

// ViewControllerC.h 
@interface ViewControllerC : UIViewController 
@property (nonatomic, copy) void (^dismissBlock)(void); 
@end 

//ViewControllerC.m 
// Make an method to handle dismissal that is called by button press or whatever logic makes sense. 
- (void)closeButtonPressed { 
    if (_dismissBlock) {// If the dismissblock property was set, let the block handle dismissing 
     _dismissBlock(); 
     return; 
    } 

    // Leaving this here simply allows the viewController to be presented modally as the base as well or allow the presenter to handle it with a block. 
    [self dismissViewControllerAnimated:YES completion:nil]; 
} 

Spero che questo aiuti, programmazione felice :)

+0

upvote per una soluzione di lavoro, ma questo è semplicemente folle (rispetto al suo vantaggio) –

+1

Lo è, ma letteralmente non c'è una buona soluzione di lavoro che sia facile e che abbia un bell'aspetto. Ero frustrato dal fatto che Apple non avesse già un buon modo di gestirlo. Spero che con la nuova versione di questo autunno. – johnrechd

+0

Assolutamente vero. Sono andato in un altro modo e ho respinto i viewControllers uno dopo l'altro (non è una soluzione al problema, ma funziona e non è _that_ brutto) –

Problemi correlati