Pregunta

Me tiene dos puntos de vista que necesitan ser mostrados de forma modal, una tras otra. Esto no funciona si desechamos y mostrar de forma consecutiva, de esta manera:

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

El segundo punto de vista modal simplemente no aparece.

he visto una corrección que fue algo como esto:

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

El problema es que esto no va a funcionar todo el tiempo (el retardo necesario es superior, a veces).

Otra solución posible sería eliminar la animación:

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

Pero realmente me gustaría mantener la animación, para mantener la sensación de que el primer modal está fuera del camino. ¿Alguna sugerencia?

¿Fue útil?

Solución

EDIT:. El mecanismo de "correcta" de hacer esto en iOS5 + sería utilizar el método – dismissViewControllerAnimated:completion:, y presentar el controlador de vista secuencial desde el bloque de terminación


El ViewController que está siendo mostrado de forma modal tendrá su viewDidDisappear: animada: método llama una vez que el modal-despido-animación es completa. AFIK este es el único lugar donde puede conectar para iniciar una presentModalViewController posterior: animación:. Llamada

tiene una clase que yo uso para la presentación de los controladores de vista modal e implementa la lógica que está buscando a través de una devolución de llamada al controlador de vista presentando una vez que el despido es completa. Para utilizar esta clase, simplemente alloc / init una instancia y presente utilizando el presentViewController normal: animada: llamada. Implementar el siguiente método en el controlador de vista la presentación de:

- (void) modalViewControllerDidDismiss:(UIViewController *)modalViewController

Esto se llama a la vez el controlador de vista modal se ha ido, y se puede presentar un nuevo controlador de vista modal en este momento.

Una cosa agradable también - ya que esta clase es una especialización de UINavigationController, se puede configurar el navigationbar de encendido / apagado a su gusto. La clase también se ha incorporado en la lógica para mostrar un botón Descartar, como te gusta.

Aquí está la definición de clase:

@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

Y la implementación de la clase:

@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

y, aquí es cómo se puede usar (en el contexto de algún controlador de vista 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];
}

y, aquí es el método despido de devolución de llamada, que presenta un nuevo controlador de vista 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];
}

Otros consejos

rootController puede decir cuando el último de los controladores de vista modal en la parte superior de la misma ha desaparecido, ya que recibirá un viewDidAppear :. ¿Ha tratado de vincular el presentModalViewController:? Del controlador de vista posterior a ese

Si realmente quiere ver animaciones múltiples cadena juntos, me sugieren realmente sólo manipular la lógica de la animación a sí mismo. No es demasiado complicado, y luego se puede tener un control preciso sobre cómo se presentan los puntos de vista. Me acabo de escribir algo similar para la otra pregunta aquí:

iOS -? ¿cómo controlar el tamaño de un controlador de vista modal

Sólo puede animar la vista en, animar la vista fuera, y cuando el selector de animationDidStop se llama, animado su segundo punto de vista sobre. La parte buena de esto es que también puede jugar con la vista la opacidad y la dirección de animación, así como decidir exactamente cuándo deben aparecer los puntos de vista. Por ejemplo, usted podría tener el segundo punto de vista vienen de deslizamiento a lo largo de la primera vista como el primer punto de vista se desliza lejos; no hay necesidad de esperar a que el primero de ellos para completar su animación.

Es el tema relacionado con "mostrar una vista modal dentro de una vista modal"? Tengo publicar una respuesta acerca de esto aquí: vista modal iPhone dentro de otro punto de vista modal?

La mejor solución que encontré para algo como esto (si es que son todos los niños iguales de la vista padre) es parchear sus puntos de vista sobre una UIScrollView con activar la paginación, (se puede agregar un control de página en la parte inferior para que quede claro y para la navegación) a continuación, añadir los puntos de vista de los controladores a la vista de la página, ya que vienen en pantalla, retire, ya que ir fuera de la pantalla.

También puede tener que -viewWillAppear llamada ficticia y -viewWillDisappear si los controladores dependen de este que se llama. Se siente un poco hackear-ish el momento de codificar todo, pero una vez que lo tienes trabajo se ve suave y natural, y no hay ninguna de la espera asociados con la animación de un punto de vista, entonces la animación de la siguiente de una vez se ha ido.

Encuentro usando -viewDidDissapear de la vista modal para invocar métodos en la presentación de los trabajos controlador de vista muy bien. Uno de los beneficios es la capacidad de retrasar la desasignación en el controlador de vista modal. Por favor, publique cualquier mejora que puedo hacer. Mi inspiración para la creación de este protocolo de vino de iOS 5 "dismissViewControllerAnimated: completado:" Además de UIViewController. Quería que esta funcionalidad en 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];

                }
            }];
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top