iPhone应用程序中的例外情况:模态转换已在进行中

时间:2010-07-09 14:47:29

标签: iphone objective-c xcode

我认为这是一个相当简单的应用程序,基于一些拼凑在一起的教程。我在OSX 10.6.4中使用XCode 3.2.3。它起初是一个标准的iPhone“基于窗口的应用程序”。使用界面构建器我在这里使用O'Reilly视频教程添加了一个Tab Bar Controller:

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

这就是我的问题所在。我尝试了很多不同的hacks和迭代,但上面的代码是最简单的问题。当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 个答案:

答案 0 :(得分:9)

要解决此处描述的具体问题,您可以在班级中添加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,否则什么也不做”。

那就是说,imho,推动模态视图通常应该是响应用户操作而完成的,我可能会在这里重新考虑用户体验 - 例如添加一个子视图,而不是推动你可以在当前拥有代码的地方进行模态视图 - 但是如果你只是在玩一些应该解决NSInternalInconsistencyException的教程。 :)干杯!

答案 1 :(得分:5)

在iOS 5.0及更高版本中,您可以使用

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

答案 2 :(得分:2)

我遇到过这个问题很多次了。我最近开始使用这个简单的修复:

当我要在解雇另一个模态视图控制器后立即呈现一个新的模态视图控制器时,我只是在dismissModalViewControllerAnimated:中忽略第一个参数为NO。

由于第二个视图带有动画,因此几乎没有注意到第一个视图快速消失。你永远不会发生过渡冲突。

答案 3 :(得分:0)

当我想在解雇UIImagePickerController后立即呈现MFMailComposeViewController时,我遇到了同样的问题。继承人我做了什么:

  1. 我从呈现图像选择器的地方删除了[imagePicker release];语句,并将其放入didFinishPickingMedia回调中。

  2. 我使用了[self performSelector:@selector(presentMailComposer:) withObject:image afterDelay:1.0f];

  3. 这是我的代码: 显示图像选择器

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

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

    Image Picker委托回调 - 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];
    

    显示邮件编辑器视图

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

    if ([MFMailComposeViewController canSendMail]) {