Question

J'ai deux points de vue qui ont besoin d'être démontré de façon modale, l'un après l'autre. Cela ne fonctionne pas si nous écartons et montrer consécutivement, comme ceci:

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

Le second point de vue modal ne fonctionne tout simplement pas montré.

Je l'ai vu une solution qui était quelque chose comme ceci:

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

Le problème est que cela ne fonctionnera pas tout le temps (le délai nécessaire est supérieur, parfois).

Une autre solution possible serait d'éliminer l'animation:

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

Mais je voudrais vraiment garder l'animation, de garder la sensation que le premier modal est hors de la voie. Toutes les suggestions?

Était-ce utile?

La solution

EDIT:. Le mécanisme « correct » pour ce faire dans iOS5 + serait d'utiliser la méthode de – dismissViewControllerAnimated:completion:, et présenter le contrôleur de vue séquentielle à partir du bloc de fin


Le viewcontroller qui est montré de façon modale aura son viewDidDisappear: animation: méthode appelée une fois le licenciement animation-modale est terminée. Afik c'est le seul endroit où vous pouvez accrocher pour initier une presentModalViewController suivante: animation. Appel

J'ai une classe que j'utilise pour présenter les contrôleurs de vue modales et il met en œuvre la logique que vous cherchez par un rappel au contrôleur de vue présentant une fois que le licenciement est terminé. Pour utiliser cette classe, tout simplement alloc / init une instance et présente en utilisant le presentViewController normal: animé: appel. Mettre en oeuvre le procédé suivant sur le contrôleur d'affichage présentant:

- (void) modalViewControllerDidDismiss:(UIViewController *)modalViewController

sera appelée à la fois le contrôleur modal de vue est parti, et vous pouvez présenter un nouveau contrôleur de vue modal à ce moment.

Une belle chose aussi - car cette classe est une spécialisation de UINavigationController, vous pouvez configurer l'navigationBar on / off que vous le souhaitez. La classe a intégré la logique de montrer également un bouton destituer, comme vous le souhaitez.

Voici la définition de la 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

Et la mise en œuvre de la 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

et, voici comment vous pouvez l'utiliser (dans le contexte de certains contrôleur de vue normal):

- (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];
}

et, voici la méthode de rappel de licenciement, qui présente un nouveau contrôleur de vue modal:

- (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];
}

Autres conseils

rootController peut dire quand le dernier des contrôleurs de vue modal sur le dessus de celui-ci a disparu parce qu'il recevra un viewDidAppear :. Avez-vous essayé lier le presentModalViewController: du contrôleur après vue que

Si vous voulez vraiment connecter plusieurs animations vue ensemble, je fait juste la manipulation suggère vous-même logique d'animation. Il est pas trop difficile, et vous pouvez avoir un contrôle à grains fins sur la façon dont les vues sont présentées. Je viens d'écrire ici quelque chose de semblable à une autre question:

iOS - comment contrôlez-vous la taille d'un contrôleur de vue modal

Vous pouvez simplement animer la vue sur, animer la vue hors tension, et lorsque votre sélecteur de animationDidStop est appelé, animé votre deuxième vue sur. La belle partie de ceci est que vous pouvez également jouer avec vue sur l'opacité et la direction de l'animation, ainsi que décider exactement quand les vues doivent apparaître. Par exemple, vous pourriez avoir la deuxième vue viennent glisser vers le haut sur la première vue comme la première vue est glisse; pas besoin d'attendre le premier à compléter son animation.

Votre problème est lié à « montrer une vue modale dans une vue modale »? J'ai poster une réponse à ce sujet ici: iPhone vue modal dans une autre vue modal?

La meilleure solution que je trouve quelque chose comme ça (s'ils sont tous égaux enfants de la vue parent) est de patcher leurs vues sur un UIScrollView avec la pagination activée, (vous pouvez ajouter un contrôle de page en bas pour le rendre clair et pour la navigation) puis ajoutez les vues des contrôleurs à la vue de la page comme ils viennent à l'écran, ils vont supprimer comme hors-champ.

Vous pouvez également avoir à l'appel factice -viewWillAppear et -viewWillDisappear si les contrôleurs se fondent sur celle-ci étant appelé. Il se sent pirater-ish un peu quand vous codez tout cela, mais une fois que vous l'avez travail il semble lisse et naturel, et il n'y a pas de l'attente associée à animant un point de vue sur, puis animant la suivante en une fois est parti.

Je trouve l'aide de la -viewDidDissapear de vue modal pour invoquer des méthodes sur le travail du contrôleur de vue est très bien présenté. L'un des avantages est la possibilité de retarder désallocation sur le contrôleur modal de la vue. S'il vous plaît poster des améliorations que je peux faire. Mon inspiration pour la création de ce protocole est venu de iOS 5 « dismissViewControllerAnimated: achèvement: » plus de UIViewController. Je voulais cette fonctionnalité dans 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];

                }
            }];
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top