Domanda

Ho due punti di vista che devono essere visualizzato come form modale, una dopo l'altra. Questo non funziona se noi respingiamo e mostrare consecutivamente, in questo modo:

[rootController dismissModalViewControllerAnimated: YES];
[rootController presentModalViewController: psvc animated: YES];

La seconda vista modale semplicemente non si presenta.

Ho visto una correzione che era qualcosa di simile a questo:

[rootController dismissModalViewControllerAnimated: YES];
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[self performSelector: @selector(seekModal) withObject: nil afterDelay: 0.5];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];

Il problema è che questo non funzionerà per tutto il tempo (il ritardo necessario è superiore, a volte).

Un'altra possibile soluzione potrebbe essere quella di eliminare l'animazione:

[rootController dismissModalViewControllerAnimated: NO];
[rootController presentModalViewController: psvc animated: YES];

Ma mi piacerebbe davvero mantenere l'animazione, per mantenere la sensazione che il primo modale è fuori strada. Qualche suggerimento?

È stato utile?

Soluzione

EDIT:. Il meccanismo "corretta" per fare questo in iOS5 + sarebbe quella di utilizzare il metodo – dismissViewControllerAnimated:completion:, e presenta al controllore vista sequenziale dal blocco completamento


Il viewcontroller che viene mostrato in modo modale avrà il suo viewDidDisappear: animato: il metodo chiamato una volta il modal-licenziamento-animazione è completa. Afik questo è l'unico posto dove si può agganciare ad avviare una successiva presentModalViewController: animato:. Chiamata

Ho una classe che uso per la presentazione dei controller di vista modale e implementa la logica si sta cercando attraverso un callback per il controller della vista di presentare una volta che il licenziamento è completo. Per utilizzare questa classe, semplicemente alloc / init un'istanza e presente con il presentViewController normale: animato: chiamata. Implementare il metodo seguente sul controller vista presentando:

- (void) modalViewControllerDidDismiss:(UIViewController *)modalViewController

Questa sarà chiamato immediatamente il controller di vista modale è andato, ed è possibile presentare un nuovo controller di vista modale in questo momento.

Una cosa bella troppo - dal momento che questa classe è una specializzazione di UINavigationController, è possibile configurare il navigationBar on / off come ti piace. La classe ha anche una logica incorporata per mostrare un pulsante di respingere, come vi piace.

Ecco la definizione della classe:

@protocol TSModalViewControllerDelegate

- (void) modalViewControllerDidDismiss: (UIViewController*) modalViewController;

@end

@interface TSModalViewController : UINavigationController 
{
    UIViewController*   _originalParentViewController;
}
@property BOOL dismissButtonHidden;

- (id) initWithViewController: (UIViewController*) vc;
- (id) initWithClass: (Class) c;
- (id) initWithClass: (Class) c nibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;

@end

E l'implementazione della classe:

@implementation TSModalViewController
@synthesize dismissButtonHidden;

- (id) initWithViewController: (UIViewController *)vc
{
    return [super initWithRootViewController: vc];
}

- (id) initWithClass:(Class)c
{
    UIViewController* vc = [[[c alloc] init] autorelease];
    return [self initWithViewController: vc];
}

- (id) initWithClass: (Class) c nibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    UIViewController* vc = [[[c alloc] initWithNibName:nibNameOrNil bundle:nibBundleOrNil] autorelease];
    return [self initWithViewController: vc];
}

- (void) viewDidAppear: (BOOL) animated
{
    [super viewDidAppear: animated];

    [_originalParentViewController release];
    _originalParentViewController = [self.parentViewController retain];

    if (!self.dismissButtonHidden)
    {
        UIBarButtonItem* dismissButton = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemStop
                                                                                        target: self 
                                                                                        action: @selector(onDismiss:)] autorelease];

        UIViewController* rootViewController = [self.viewControllers objectAtIndex:0];

        rootViewController.navigationItem.leftBarButtonItem = dismissButton;
        self.navigationBarHidden = NO;
    }   
}

- (void) viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear: animated];
    if ( [_originalParentViewController respondsToSelector: @selector(modalViewControllerDidDismiss:)] )
    {
        [_originalParentViewController performSelector: @selector(modalViewControllerDidDismiss:) withObject: self];
    }
}

- (void) dismissModalViewControllerAnimated:(BOOL)animated
{
    return [self.parentViewController dismissModalViewControllerAnimated: animated];
}

- (void) onDismiss: (id) sender
{
    [self.parentViewController dismissModalViewControllerAnimated: YES];
}

- (void) didReceiveMemoryWarning 
{
    [super didReceiveMemoryWarning];
}

- (void) viewDidUnload 
{
    [super viewDidUnload];
}

- (void)dealloc 
{
    [_originalParentViewController release];
    [super dealloc];
}

@end

e, ecco come si può utilizzare (nel contesto di qualche normale controller della vista):

- (void) onShowIt:(id)sender
{
    TSModalViewController* mvc = [[[TSModalViewController alloc] initWithClass: [MyModalViewController class] nibName: @"MyModalViewController" bundle:nil] autorelease];
    mvc.dismissButtonHidden = YES;  // set to no if you don't want an "automatic" close button

    [self presentModalViewController: mvc animated: YES];
}

e, qui è il metodo di licenziamento di callback, che presenta un nuovo controller di vista modale:

- (void) modalViewControllerDidDismiss:(UIViewController *)modalViewController
{
    MyModalViewController* vc = [[[MyModalViewController alloc] initWithNibName: @"MyModalViewController" bundle:nil] autorelease];
    vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;

    TSModalViewController* mvc = [[[TSModalViewController alloc] initWithViewController: vc] autorelease];

    [self presentModalViewController: mvc animated: YES];
}

Altri suggerimenti

rootController può dire quando l'ultimo della vista controllori modali su di esso è scomparso perché riceverà una viewDidAppear :. Hai provato che collega la presentModalViewController:? Della successiva controller della vista a quella

Se si vuole veramente per visualizzare la catena più animazioni insieme, vorrei davvero suggerisco solo gestire la logica di animazione da soli. Non è troppo difficile, e quindi si può avere il controllo a grana fine su come i punti di vista sono presentati. Ho appena scritto qualcosa di simile per un'altra domanda qui:

iOS -? come si fa a controllare la dimensione di un controller di vista modale

Si può solo animare la vista, animare la vista fuori, e quando il selettore di animationDidStop si chiama, animato tua seconda vista. La bella parte di questo è che si può anche giocare con vista l'opacità e la direzione dell'animazione, così come decidere esattamente quando dovrebbero comparire i punti di vista. Ad esempio, si potrebbe avere la seconda Guarda Come scorrere fino oltre la prima vista come la prima vista è scivolare via; non c'è bisogno di aspettare il primo a completare la sua animazione.

è il problema correlate a "mostrare una vista modale all'interno di una vista modale"? Ho inviare una risposta su questo qui: iPhone vista modale all'interno di un'altra vista modale?

La soluzione migliore che ho trovato qualcosa di simile (se sono tutti i bambini pari della vista padre) è di rattoppare il loro parere su un UIScrollView con paginazione abilitato, (è possibile aggiungere un controllo di pagina in fondo per far capire e per la navigazione) quindi aggiungere il punto di vista dei controllori per la visualizzazione della pagina come vengono sullo schermo, rimuovere come vanno fuori dallo schermo.

Si può anche avere alla chiamata manichino -viewWillAppear e -viewWillDisappear se i controller si basano su questo essere chiamato. Ci si sente un po incidere-ish quando si codifica tutto, ma una volta che lo avete a lavorare esso appare liscia e naturale, e non v'è alcuna della attesa associati animare una vista fuori, quindi animando il prossimo in una volta è andato.

Trovo usando -viewDidDissapear della vista modale per invocare metodi sulla presentazione delle attività vista del regolatore è molto bene. Uno dei vantaggi è la possibilità di ritardare deallocazione sul controller di vista modale. Si prega di inviare eventuali miglioramenti che posso fare. La mia ispirazione per la creazione di questo protocollo è venuto da iOS 5 di "dismissViewControllerAnimated: completamento:" Oltre a UIViewController. Ho voluto questa funzionalità in iOS 4.3.


PresentorDelegateProtocol.h

@protocol PresentorDelegateProtocol <NSObject>
@optional

/* 

Extra protocol methods defined in protocol for flexibility.  
Main methods are:
- (void)dismissPresentingModalViewController:(id)modalView animated:(BOOL)animated; 
- (void)modalViewDissapeared:(id)modalView;  //used in modal view's -viewDidDissapear

*/

- (void)dismissPresentingModalViewController:(id)modalView animated:(BOOL)animated;
- (void)modalViewDissapeared:(id)modalView; 

// use the block in this method send messages to save state, etc.  This is the one I like to use.
- (void)dismissPresentingModalViewController:(id)modalView animated:(BOOL)animated withBlock:(void(^)())block;

// use in other classes that are not controlling dismissal of the modal view
- (void)executeBlockOnModalDissapearance: (void(^)())block;

@end

PresentingViewController.h

#import "PresentorDelegateProtocol.h"
@interface PresentingViewController : UIViewController <PresentorDelegateProtocol>
- (void)showModalVC;
@end

ModalViewController.h

#import "PresentorDelegateProtocol.h"
@interface ModalViewController : UIViewController
@property (nonatomic, assign) id <PresentorDelegateProtocol> presentorDelegate;
- (void)close;
@end

PresentingViewController.m

#import "PresentingViewController.h"
#import "ModalViewController.h"
@implementation PresentingModalViewController
- (void)showModalVC
{
    ModalViewController *modalVC = [[ModalViewController alloc] initWithNibName:@"ModalViewController" bundle:nil];
    modalVC.presentorDelegate = self;
    [self presentModalViewController:modalVC animated:YES];
}
- (void)dismissPresentingModalViewController:(id)modalView animated:(BOOL)animated
{
    if ([modalView isKindOfClass:[ModalViewController class]]) {
        NSLog(@"Can invoke based on class"); 
    }
    [self dismissModalViewControllerAnimated:animated];    
}
- (void)dismissPresentingModalViewController:(id)modalView animated:(BOOL)animated withBlock:(void(^)())block
{
    block();  
    /* execute block before or after calling to dismiss modal view */
    [self dismissPresentingModalViewController:modalView animated:animated];
    //block();
}
- (void)modalViewDissapeared:(id)modalView
{
    if ([modalView isKindOfClass:[ModalViewController class]]) {
        NSLog(@"Do stuff based on class.");
    }
}
- (void)executeBlockOnModalDissapearance: (void(^)())block
{
    block();
    NSLog(@"This delay's dealloc on modal view until block completes");
}
@end

ModalViewController.m

#import "ModalViewController.h"
@implementation ModalViewController
@synthesize presentorDelegate;

- (void)close
{
    if (1 == 0 /*need to do something before dealloc*/){
        [self.presentorDelegate dismissPresentingModalViewController:self animated:YES withBlock:^{
            NSLog(@"Do stuff with block.  Save, animate, etc");
        }];

    } else {
        [self.presentorDelegate dismissPresentingModalViewController:self animated:YES];
    }
}

- (void)viewDidDisappear:(BOOL)animated
{
    if (1 == 0 /*stuff to do*/){
        [self.presentorDelegate executeBlockOnModalDissapearance:^{
        // do stuff before modal view is deallocated
        }];
    }
    [self.presentorDelegate modalViewDissapeared:self];

    presentorDelegate = nil;
    [super viewDidDisappear:animated];
}
@end;
// present modal view inside another presented modal view

    FirstViewController *firstVC = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil];
    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController: firstVC];

    // Note: you can use your viewcontroller instead self.window.rootViewController

    [self.window.rootViewController presentViewController:navController animated:YES completion:^{
                //code...
                    SecondViewController *secondVC = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];

                    [navController presentViewController: secondVC animated:YES completion:nil];

                }
            }];
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top