2010-07-09 9 views
7

Ho in pratica quello che ritengo sia un'applicazione abbastanza semplice basata su alcuni tutorial accartocciati insieme. Sto usando XCode 3.2.3 in OSX 10.6.4. È iniziato come un'applicazione standard basata su Windows per iPhone. Utilizzando interface builder ho aggiunto un Tab Bar controller utilizzando il video tutorial O'Reilly qui:Eccezione nell'app per iPhone: la transizione modale è già in corso

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

nella prima scheda ho un UIView di serie con due pulsanti. Entrambi chiamano la stessa funzione per visualizzare 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]; 
} 

Sono in esecuzione il codice all'interno di un emulatore in modo sempre e solo fare clic sul pulsante chiamato Seleziona immagine. Quando il dialogo viene rilasciato con una foto scelta questa funzione viene eseguito:

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

Questo è dove il mio problema. Ho provato diversi tipi di hack e iterazioni, ma il codice precedente è il più semplice per presentare il problema. Quando l'imageViewController viene visualizzato come un dialogo modale viene lanciata la seguente eccezione:

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' 

Come faccio a curare questo? Ho provato ritardi e altri trucchi ma non capisco davvero come dovrei usare viewDidAppear o viewDidDisappear per aiutarmi. Si noti inoltre che un'applicazione molto semplice con una vista che carica il selettore e quindi visualizza un'altra vista con l'immagine in non produce l'errore. Qualsiasi aiuto ricevuto con gratitudine.

risposta

9

per affrontare il problema specifico descritto qui, si potrebbe aggiungere il metodo viewDidAppear nella classe:

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

rimuovere quelle linee dal basso la chiamata:

[picker dismissModalViewControllerAnimated:YES]; 

Così, ogni volta che la vostra classe self appare (viene visualizzato), chiamerà viewDidAppear ... Dal momento che molto probabilmente non è davvero quello che vuoi sempre, potresti aggiungere alcune variabili da impostare/cancellare che definiscono se o non im presenta immediatamente lo imageViewController quando viene visualizzato self. Qualcosa come "Se provieni dal selettore di immagini, mostra il controller imageView, altrimenti non fare nulla".

Detto questo, imho, spingere le visualizzazioni modali dovrebbe generalmente essere fatto in risposta a un'azione dell'utente e vorrei forse ripensare l'esperienza utente qui - ad es. aggiungi una sottoview invece di spingere una vista modale che potresti fare dove attualmente hai il codice - ma se stai solo giocando con alcuni tutorial che dovrebbero risolvere NSInternalInconsistencyException. :) Saluti!

+0

Grazie per i consigli, cercherò che nel mio codice come è più ordinato di quello che sto facendo. Sto premendo la vista modale dopo che l'utente ha scattato una foto o selezionato una foto. L'idea qui è che c'è un po 'di elaborazione delle immagini potenzialmente intensa e voglio mostrarlo modamente all'utente fino al suo completamento. Quindi c'è un'azione dell'utente prima di forzare la vista modale. Come una parte ho infine ucciso l'eccezione con questo:

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

+0

OK picker.view.superview removeFromSuperview. Davvero una pessima soluzione a meno che non ti piacciano gli schermi vuoti per tutto in seguito! Ho ricostruito l'app da zero alla fine utilizzando un controller della barra di navigazione all'interno di un'app tab tab e questo ha funzionato correttamente. In un'altra nota, anche la tua soluzione ha funzionato. Grazie. Molto più chiaro ora. L'ho fatto solo per 2 giorni da uno sfondo C/C++/Java/Perl/bash. – Diziet

0

Avevo lo stesso problema quando volevo presentare un MFMailComposeViewController subito dopo aver chiuso UIImagePickerController. Heres quello che ho fatto:

  1. ho rimosso la dichiarazione [imagePicker release]; da dove ho presentato il selettore di immagini e metterlo in didFinishPickingMedia callback.

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

Ecco il mio codice: Visualizzazione immagine Picker

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

Immagine Picker Delegato di richiamata - 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 posta Compositore View

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

mi sono imbattuto in questa edizione un bel paio di volte. Recentemente ho iniziato a utilizzare questa semplice correzione:

Quando ho intenzione di presentare un nuovo controller di visualizzazione modale immediatamente dopo aver chiuso un altro controller di visualizzazione modale, semplicemente congedo il primo con argomento NO in dismissModalViewControllerAnimated:.

Poiché la seconda vista è presentata con un'animazione, si nota a malapena che il primo scompare rapidamente. E non si ottiene mai il conflitto delle transizioni.

5

In iOS 5.0 e superiori è possibile utilizzare

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

È molto utile. – Diziet

+0

risolto i miei problemi di navigazione. Grazie –

Problemi correlati