多个模态视图转换崩溃应用程序

时间:2009-07-23 16:42:52

标签: iphone cocoa-touch

我想按顺序呈现多个模态视图(例如,从图像选择器中选择图片后显示确认页面)。我的问题是,在没有延迟的后续步骤中解雇和呈现的动画总是会使用EXC_BAD_ACCESS使应用程序崩溃。

我认为问题在于CoreAnimation没有区分两个转换,并且无法正确检测第一个转换是否已经结束。

到目前为止,我的工作是引入1段延迟,似乎可以解决问题。但是,我认为这会使代码有点脆弱。还有另一种解决方法吗?

这是UIKit中的错误吗?我应该提交错误报告吗?

示例代码

这是一个重现崩溃的简单案例:

  1. 使用以下类创建一个新的基于视图的项目作为主控制器的实现

  2. 出现图像选择器视图时点击'取消'

  3. 预期行为:由于viewDidAppear中的后续调用,选择器视图被解除并再次显示。

    实际行为:它与下面显示的堆栈跟踪崩溃。

    代码:

    
    #import "SampleViewController.h"
    
    @implementation SampleViewController
    
    - (void)showModal {
        UIImagePickerController *picker = [[UIImagePickerController alloc] init];
        [self presentModalViewController:picker animated:YES];
        // [picker release];
    }
    
    - (void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
        [self showModal]; // this line crashes the app
        // the following works as desired
        // [self performSelector:@selector(showModal) withObject:nil afterDelay:1];
    }
    
    @end
    

    崩溃堆栈跟踪:

    #0  0x30b43212 in -[UIWindowController transitionViewDidComplete:fromView:toView:]
    #1  0x3095828e in -[UITransitionView notifyDidCompleteTransition:]
    #2  0x3091af0d in -[UIViewAnimationState sendDelegateAnimationDidStop:finished:]
    #3  0x3091ad7c in -[UIViewAnimationState animationDidStop:finished:]
    #4  0x00b54331 in run_animation_callbacks
    #5  0x00b54109 in CA::timer_callback
    #6  0x302454a0 in CFRunLoopRunSpecific
    #7  0x30244628 in CFRunLoopRunInMode
    #8  0x32044c31 in GSEventRunModal
    #9  0x32044cf6 in GSEventRun
    #10 0x309021ee in UIApplicationMain
    #11 0x00002794 in main at main.m:14
    

1 个答案:

答案 0 :(得分:8)

您需要让动画上下文完成。正如您已经发现的那样

[self performSelector:@selector(showModal)withObject:nil afterDelay:1];

有效,但很明显,延迟并不好,所以这样做:

[self performSelector:@selector(showModal) withObject:nil afterDelay:0.0];

当你使用afterDelay:0.0它不会直接调用选择器,而是将你的runloop上的调用排入队列,这会让你所有的状态(自动释放池,动画上下文等)都正确地调用,然后立即调用你的调用runloop开始处理事件。

可能出现问题的一个问题是,用户可以通过点击屏幕来关闭UIEvents,但是你可以通过在动画启动之前调用它来解决这个问题

[[UIApplication sharedApplication] beginIgnoringInteractionEvents];

这一旦你在屏幕上有你的最终模态

[[UIApplication sharedApplication] endIgnoringInteractionEvents];

通常,您希望在动画快速过渡时花费UI交互。