Исключение в приложении для iPhone: модальный переход уже выполняется - PullRequest
7 голосов
/ 09 июля 2010

У меня есть, на мой взгляд, довольно простое на данный момент приложение, основанное на нескольких выложенных вместе уроках. Я использую XCode 3.2.3 в OSX 10.6.4. Это началось как стандартное iPhone "Window Based Application". Используя конструктор интерфейса, я добавил контроллер панели вкладок, используя видеоурок O'Reilly здесь:

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

В первой вкладке у меня есть стандартный UIView с двумя кнопками. Оба вызывают одну и ту же функцию для отображения 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];
}

Я запускаю код внутри эмулятора, поэтому нажимаю только кнопку «Выбрать фото». Когда диалог открывается с выбранной фотографией, эта функция запускается:

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

Вот где моя проблема. Я пробовал много разных хаков и итераций, но приведенный выше код является самым простым, чтобы представить проблему. Когда imageViewController отображается как модальный диалог, выдается следующее исключение:

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'

Как мне это вылечить? Я пробовал задержки и другие приемы, но не совсем понимаю, как мне использовать viewDidAppear или viewDidDisappear, чтобы помочь мне. Также следует отметить, что очень простое приложение с одним представлением, загружающим средство выбора и затем отображающее другое представление с изображением, не выдает ошибку. Любая помощь с благодарностью получена.

Ответы [ 4 ]

9 голосов
/ 10 июля 2010

Чтобы решить конкретную проблему, описанную здесь, вы можете добавить метод viewDidAppear в ваш класс:

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

Удалите эти строки из-под вашего вызова:

[picker dismissModalViewControllerAnimated:YES];

Так что всякий раз, когдаВаш класс self появляется (отображается), он будет вызывать viewDidAppear ... Поскольку это, скорее всего, не действительно , что вы хотите все время, вы можете добавить некоторые переменные для установки / очисткиэто определяет, следует ли немедленно представить imageViewController при отображении self.Что-то вроде «Если исходить из средства выбора изображений, показать imageViewController, в противном случае ничего не делать».

Тем не менее, имхо, продвижение модальных представлений, как правило, должно быть сделано в ответ на действие пользователя, и я мог бы переосмыслить пользователяопыт здесь - например, добавьте подпредставление вместо нажатия модального представления, которое вы могли бы сделать там, где у вас в данный момент есть код, - но если вы просто играете с некоторыми учебными пособиями, которые должны решить NSInternalInconsistencyException.:) Ура!

5 голосов
/ 05 ноября 2012

В iOS 5.0 и выше вы можете использовать

[self dismissViewControllerAnimated:YES completion:^{
  //present another modal view controller here
}];
2 голосов
/ 29 марта 2012

Я сталкивался с этой проблемой довольно много раз.Недавно я начал использовать это простое исправление:

Когда я собираюсь представить новый контроллер модального вида сразу после закрытия другого контроллера модального представления, я просто отклоняю первый с аргументом NO в dismissModalViewControllerAnimated:.

Поскольку второй вид представлен с анимацией, вы вряд ли заметите, что первый вид исчезает быстро.И вы никогда не получите конфликт переходов.

0 голосов
/ 28 марта 2011

У меня возникла такая же проблема, когда я хотел представить MFMailComposeViewController сразу после закрытия UIImagePickerController. Вот что я сделал:

  1. Я удалил оператор [imagePicker release];, из которого я представлял средство выбора изображений, и поместил его в обратный вызов didFinishPickingMedia.

  2. Я использовал [self performSelector:@selector(presentMailComposer:) withObject:image afterDelay:1.0f];

Вот мой код: Отображение палитры изображений

if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { NSArray *media = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypePhotoLibrary];</p> <pre><code> 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]; }

Обратный вызов делегата средства выбора изображений - didFinishPickingMedia

NSString *mediaType = [info valueForKey:UIImagePickerControllerMediaType];</p> <pre><code>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];

Просмотр представления Composer Mail

if ([MFMailComposeViewController canSendMail]) {</p> <pre><code> 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:@"hello@xische.com"]]; [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]; }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...