2010-07-09 8 views
7

tengo lo que creo es una aplicación bastante sencilla en el momento en base a algunos tutoriales improvisado. Estoy usando XCode 3.2.3 en OSX 10.6.4. Comenzó como un iPhone estándar "Aplicación basada en la ventana". El uso de constructor de interfaces he añadido un controlador de barra de pestañas usando el video tutorial O'Reilly aquí:Excepción en aplicación de iPhone: Modal de transición ya está en marcha

http://broadcast.oreilly.com/2009/06/tab-bars-and-navigation-bars-t.html

En la primera pestaña Tengo un UIView estándar con dos botones. Ambos llaman la misma función para mostrar un UIImagePickerController:

-(IBAction) btnPhotoClicked:(id)sender { 
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; 
imagePicker.delegate = self; 
if((UIButton *)sender == btnChoosePhoto) 
{ 
    imagePicker.allowsEditing = YES; 
    imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; 
} else { 
    imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera; 
} 

[self presentModalViewController:imagePicker animated:YES]; 
[imagePicker release]; 
} 

Me postulo el código dentro de un emulador de manera única cada vez haga clic en el botón de llamada Elija las fotos. Cuando el diálogo se libera con una foto elegido esta función se ejecuta:

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { 
NSURL *mediaUrl; 

mediaUrl = (NSURL *)[info valueForKey:UIImagePickerControllerMediaURL]; 

if (mediaUrl == nil) 
{ 
    imagePuzzle = (UIImage *) [info valueForKey:UIImagePickerControllerEditedImage]; 
    if(imagePuzzle == nil) 
    { 
     //--- Original Image was selected --- 
     imagePuzzle = (UIImage *) [info valueForKey:UIImagePickerControllerOriginalImage]; 
    } 
    else { 
     //--- Get the edited image --- 
     //--- If it was successful the above valueForKey:UIImagePickerControllerEditedImage 
     //--- would have assigned it already. 
    } 
} 
else { 
    //--- Muppet selected a video 
} 

// Animate the picker window going away 
[picker dismissModalViewControllerAnimated:YES]; 
ImageViewController *imageViewController = [[ImageViewController alloc] init]; 
imageViewController.delegate = self;  
[self presentModalViewController:imageViewController animated:YES]; 
[imageViewController release]; 
} 

Aquí es donde radica mi problema. He intentado muchos hacks e iteraciones diferentes, pero el código anterior es el más simple para presentar el problema. Cuando el imageViewController se muestra como un diálogo modal, se lanza la siguiente excepción:

2010-07-09 15:29:29.667 Golovomka[15183:207] *** Terminating app due to uncaught 
exception 'NSInternalInconsistencyException', reason: 'Attempting to begin a modal 
transition from <NewViewController: 0x5915f80> to <ImageViewController: 0x594a350>  
while a transition is already in progress. Wait for viewDidAppear/viewDidDisappear 
to know the current transition has completed' 

¿Cómo puedo solucionar esto? He intentado con retrasos y otros trucos, pero realmente no entiendo cómo se supone que debo usar viewDidAppear o viewDidDisappear para ayudarme. También es de notar que una aplicación muy básica con una vista cargando el selector y luego mostrando otra vista con la imagen no produce el error. Cualquier ayuda recibida con gratitud

Respuesta

9

Para abordar la cuestión específica descrita aquí, se podría añadir el método viewDidAppear en su clase:

-(void)viewDidAppear:(BOOL)animated 
{ 
    if (/*just visited ImagePicker*/) 
    { 
     ImageViewController *imageViewController = [[ImageViewController alloc] init]; 
     imageViewController.delegate = self;  
     [self presentModalViewController:imageViewController animated:YES]; 
     [imageViewController release]; 
    } 
} 

eliminar esas líneas desde abajo su llamada:

[picker dismissModalViewControllerAnimated:YES]; 

Por lo tanto, siempre que su clase self aparece (se muestra), se llamará viewDidAppear ... Desde lo más probable no es realmente lo que quiere todo el tiempo, se podría añadir algunas variables para establecer/clara que defina si desea o no im mediatamente presentar el imageViewController cuando se visualiza self. Algo así como "Si proviene del selector de imágenes, muestre el imageViewController, de lo contrario, no haga nada".

Dicho esto, en mi humilde opinión, empujando vistas modal se debe generalmente ser hecho en respuesta a una acción del usuario y me gustaría tal vez reconsiderar la experiencia del usuario aquí - por ejemplo, agregar una vista secundaria en lugar de empujar una vista modal que se podía hacer en su momento, tienen el código - pero si sólo está jugando con algunos tutoriales que debe resolver el NSInternalInconsistencyException. :) ¡Salud!

+0

Gracias por el consejo, voy a tratar de que en mi código, ya que es más limpio que lo que estoy haciendo. Estoy presionando la vista modal después de que el usuario tomó una foto o seleccionó una foto. La idea aquí es que hay un procesamiento de imagen potencialmente intenso y quiero mostrarlo modalmente al usuario hasta que se complete. Entonces, hay una acción del usuario involucrada antes de forzar la vista modal. Como un lado finalmente maté la excepción con esto:

[picker dismissModalViewControllerAnimated: YES]; [picker.view.superview removeFromSuperview];
Diziet

+0

Aceptar picker.view.superview removeFromSuperview. ¡Una solución realmente mala a menos que te gusten las pantallas en blanco para todo después! Reconstruí la aplicación desde cero al final usando un controlador de barra de navegación dentro de una aplicación de barra de pestañas y funcionó bien. En otra nota, tu solución también funcionó. Gracias. Mucho más claro ahora. Solo he estado haciendo esto durante 2 días desde un fondo de C/C++/Java/Perl/bash. – Diziet

0

que estaba teniendo el mismo problema cuando i quería presentar un MFMailComposeViewController inmediatamente después de que se desestima el UIImagePickerController. Esto es lo que hice:

  1. que eliminan la declaración [imagePicker release]; de donde yo estaba presentando el selector de imágenes y la puso en didFinishPickingMedia de devolución de llamada.

  2. que utilizan [self performSelector:@selector(presentMailComposer:) withObject:image afterDelay:1.0f];

Aquí está mi código: Viendo del selector de imágenes

if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { NSArray *media = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypePhotoLibrary];

if ([media containsObject:(NSString*)kUTTypeImage] == YES) { 
     UIImagePickerController *picker = [[UIImagePickerController alloc] init]; 
     [picker setMediaTypes:[NSArray arrayWithObject:(NSString *)kUTTypeImage]]; 
     picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; 
     picker.delegate = self; 
     [self presentModalViewController:picker animated:YES]; 
     //[picker release]; 
    } 

} 
else { 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Unavailable!" 
                message:@"Could not open the Photo Library." 
                delegate:nil 
              cancelButtonTitle:@"OK" 
              otherButtonTitles:nil]; 
    [alert show]; 
    [alert release]; 
} 

del selector de imágenes delegado de devolución de llamada - didFinishPickingMedia

NSString *mediaType = [info valueForKey:UIImagePickerControllerMediaType];

if([mediaType isEqualToString:(NSString*)kUTTypeImage]) { 
    UIImage *photoTaken = [info objectForKey:@"UIImagePickerControllerOriginalImage"]; 

    //Save Photo to library only if it wasnt already saved i.e. its just been taken 
    if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) { 
     UIImageWriteToSavedPhotosAlbum(photoTaken, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); 
    } 

    //Pull up MFMailComposeView Controller 
    [self performSelector:@selector(composeMailWithPhoto:) withObject:photoTaken afterDelay:1.0f]; 
} 

[picker dismissModalViewControllerAnimated:YES]; 
[picker release]; 

Display Mail Compositor Ver

if ([MFMailComposeViewController canSendMail]) {

MFMailComposeViewController *mailPicker = [[MFMailComposeViewController alloc] init]; 
    mailPicker.mailComposeDelegate = self; 

    // Fill out the email fields and Attach photograph to mail 
    static NSString *imageType = @"image/jpeg"; 
    NSString *imageName = [NSString stringWithString:@"MyCoffeeCup.jpg"]; 
    NSData *imageData = UIImageJPEGRepresentation(image, 1.0); 

    [mailPicker addAttachmentData:imageData mimeType:imageType fileName:imageName]; 
    [mailPicker setToRecipients:[NSArray arrayWithObject:@"[email protected]"]]; 

    [self presentModalViewController:mailPicker animated:YES]; 
    //[self.navigationController pushViewController:mailPicker animated:YES]; 
    [mailPicker release]; 
} 
else { 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Unavailable!" 
                message:@"This device cannot send emails." 
                delegate:nil 
              cancelButtonTitle:@"OK" 
              otherButtonTitles:nil]; 
    [alert show]; 
    [alert release]; 
} 

2

me encontré con este tema unas cuantas veces. Recientemente comencé a usar esta solución simple:

Cuando voy a presentar un nuevo controlador de vista modal inmediatamente después de descartar otro controlador de vista modal, simplemente descarto el primero con el argumento NO en dismissModalViewControllerAnimated:.

Dado que la segunda vista se presenta con una animación, apenas se nota que la primera se va rápido. Y nunca obtienes el conflicto de transición.

5

En iOS 5.0 y superior se puede utilizar

[self dismissViewControllerAnimated:YES completion:^{ 
    //present another modal view controller here 
}]; 
+0

Eso es bastante útil. – Diziet

+0

Resolvió mis problemas de navegación. Gracias –

Cuestiones relacionadas