呈现模态视图控制器时 iPhone 崩溃

Posted

技术标签:

【中文标题】呈现模态视图控制器时 iPhone 崩溃【英文标题】:iPhone crashing when presenting modal view controller 【发布时间】:2010-11-27 13:48:35 【问题描述】:

我试图在另一个视图以模态方式呈现后立即显示一个模态视图(第二个是出现的加载视图)。

- (void)viewDidAppear:(BOOL)animated 
    [super viewDidAppear:animated];
    // Show load
    LoadViewController *loader = [[LoadViewController alloc] init];
    [self presentModalViewController: loader animated:NO];
    [loader release];

但是当我这样做时,我得到一个“程序接收信号:”EXC_BAD_ACCESS“。”错误。

堆栈跟踪是:

0  0x30b43234 in -[UIWindowController transitionViewDidComplete:fromView:toView:]
1  0x3095828e in -[UITransitionView notifyDidCompleteTransition:]
2  0x3091af0d in -[UIViewAnimationState sendDelegateAnimationDidStop:finished:]
3  0x3091ad7c in -[UIViewAnimationState animationDidStop:finished:]
4  0x0051e331 in run_animation_callbacks
5  0x0051e109 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 0x00002154 in main at main.m:14

有什么想法吗?我完全被难住了!加载视图是空的,所以肯定没有任何事情会导致错误。这与在同一个事件循环中以模态方式启动 2 个视图有关吗?

谢谢,

迈克

编辑:很奇怪……我稍微修改了一下,加载视图会在一点延迟后显示,这很好用!所以它似乎在同一个事件循环中!

- (void)viewDidAppear:(BOOL)animated 
    [super viewDidAppear:animated];
    // Show load
    [self performSelector:@selector(doit) withObject:nil afterDelay:0.1];


- (void)doit 
    [self presentModalViewController:loader animated:YES];  

【问题讨论】:

EXC_BAD_ACCESS 是从哪里来的?你在这里给了我们一个堆栈跟踪,但我不确定这个代码块中是否发生了错误。您能否编辑帖子以向我们提供包含所有线程所在位置的完整日志? 我不确定它来自哪里。那是我唯一的痕迹,看起来错误的访问不是来自我的代码,所以它是内部访问的东西,所以我无法查明它!我已确保所有内容都已保留,所以我不知道发生了什么! 尝试将loader 放入自动释放池中。我认为加载器消失得太快了,可能是因为当前视图控制器必须为新视图和视图控制器让路。其他想法:使用调试器和监视加载器。如果它是造成问题的原因,您会以这种方式发现它。如果没有,请继续在调试器中四处寻找,您可能会弄明白。 好的,我试试看。如何使用调试器查看加载程序?通过使用断点?或者还有其他方法可以监控除此之外的事情吗?有兴趣知道是否有其他调试方法! 我认为循环的原因是您正在加载的新视图控制器默认情况下有一个视图确实出现了方法,并且它具有 [super viewdidappear animated];这意味着它将再次回调您的主视图控制器的 viewDidAppear,就像它会循环一样 【参考方案1】:

我已经稍微修改了它,以便在稍微延迟后显示加载视图,这很好用!所以它似乎在同一个事件循环中!

- (void)viewDidAppear:(BOOL)animated 
    [super viewDidAppear:animated];
    // Show load
    [self performSelector:@selector(doit) withObject:nil afterDelay:0.1];


- (void)doit 
    [self presentModalViewController:loader animated:YES];  

【讨论】:

伙计,我一直在努力解决这个问题。感谢您的帮助! 我怀疑它也会以 0.0f 的延迟工作,那么。基本上,它将在运行循环的下一次迭代中呈现,基本上是立即呈现。 这也发生在我身上......只是它带有工具栏......您似乎无法为操作(选择器)设置延迟。 :\ 如果此修复对某些人不起作用,我发现如果您不小心连续两次快速调用presentModalViewController,也会出现此错误消息。 即使延迟 5 秒,它仍然会崩溃。【参考方案2】:

我相信我在 ios 4 中重现了相同的错误。在我的应用程序中,当尝试在显示第一个模态视图后立即显示第二个模态视图时始终发生崩溃。我挣扎了几个小时发疯了。

在阅读了该线程中的帖子后,我尝试使用标签栏应用程序模板创建一个简单的可重现示例。在响应“FirstViewController.m”中的按钮单击后,我能够使用 UIImagePickerController 显示第一个模式视图。当我尝试再次显示 UIImagePickerController 时(在处理 imagePickerControllerDidCancel 消息之后),应用程序崩溃并出现同样的错误。

在设备上,根本不知道发生了什么。然而,当我在模拟器上运行代码时,我很幸运地在控制台上收到了这条消息:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Attempting to begin a modal transition from to while a transition is already in progress. Wait for viewDidAppear/viewDidDisappear to know the current transition has completed'

所以看来我唯一的选择是遵循错误消息的建议,只需等待 viewDidAppear(使用标志表示我处于此特殊模式),然后加载第二个模式视图。

这是完整的堆栈跟踪:

** 在第一次抛出时调用堆栈: ( 0 核心基础 0x0238c919 __exceptionPreprocess + 185 1 libobjc.A.dylib 0x024da5de objc_exception_throw + 47 2 CoreFoundation 0x02345078 + [NSException raise:format:arguments:] + 136 3 基础 0x000ab8cf -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116 4 UIKit 0x00544317-[UIWindowController 转换:fromViewController:toViewController:target:didEndSelector:] + 212 5 UIKit 0x0035c769-[UIViewController presentModalViewController:withTransition:] + 2937 6 TestTempDelete 0x000021cf -[FirstViewController showImagePicker] + 167 7 基础 0x0002fcea __NSFireDelayedPerform + 441 8 核心基础 0x0236dd43 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 19 9 核心基础 0x0236f384 __CFRunLoopDoTimer + 1364 10 核心基础 0x022cbd09 __CFRunLoopRun + 1817 11 核心基础 0x022cb280 CFRunLoopRunSpecific + 208 12 核心基础 0x022cb1a1 CFRunLoopRunInMode + 97 13 图形服务 0x02bf12c8 GSEventRunModal + 217 14 图形服务 0x02bf138d GSEventRun + 115 15 UIKit 0x002beb58 UIApplicationMain + 1160 16 TestTempDelete 0x00001eb4 主要 + 102 17 TestTempDelete 0x00001e45 开始 + 53

希望这会有所帮助。

【讨论】:

【参考方案3】:

**如前所述,使用 isIgnoringInteractionEvents

//Check if the app is ignoring interatctions, if so, add a delay for 1 sec
if([[UIApplication sharedApplication] isIgnoringInteractionEvents]==TRUE) 
        [currentViewController performSelector:@selector(presentModalViewController:animated:) withObject:screen afterDelay:1];
     else 
        [currentViewController presentModalViewController:screen animated:YES];
    

【讨论】:

这适用于我的情况......但是我不确定它如何正确传递“动画”标志......很可能它被设置为一些碰巧非零的垃圾值. 救命!! :) 如果想从后台方法呈现视图,这很有效。【参考方案4】:

如果您在单击与 Interface Builder 中的代码链接的按钮后收到此信息,则可能有两个操作链接到一个按钮(也许如果您有一个链接到按钮的模态视图,那么复制按钮并链接另一个模式视图)。这将尝试将它们都关闭,因此它将失败并显示该消息。

【讨论】:

【参考方案5】:

我遇到了同样的异常

由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“尝试在转换已经在进行时开始从 到 的模态转换。等待 viewDidAppear/viewDidDisappear 知道当前转换已经完成'

如前所述,我尝试延迟呈现模态转换,但这并没有真正帮助。然后我发现我有多个 IBAction 连接到我的按钮的 TouchUpInside 事件!!!。在我的情况下,将启动两个 IBAction:模态显示人物选择器和模态显示图像选择器。这解释了错误消息。检查您是否连接了多个 IBAction!

【讨论】:

【参考方案6】:

你的问题很可能出在初始化并呈现viewDidAppear所在方法的方法上,或者在LoadViewController的init/viewDidLoad/viewWillAppear方法中。

设置一些断点并跟随直到崩溃...

【讨论】:

这些方法几乎是空的。我所做的就是更改 viewDidLoad: 上的背景颜色。应用程序很好地执行了这些行,我的代码中没有发生崩溃,当稍后在事件循环中执行其他事情时它会崩溃。【参考方案7】:

单击UIButton 打开Modal View 时,我遇到了类似的错误。我将UIButton's 监听器从UIControlEventAllEvents 更改为UIControlEventTouchUpInside。基本上,它在Touch Down Inside 上触发模态视图,然后在Touch Up Inside 上再次触发。

【讨论】:

好答案。概括它:注意打开模态视图的代码,并确保它只被调用一次。不必来自按钮点击。【参考方案8】:

由于名称不匹配,我遇到了同样的问题

HelpViewController *controller = [[HelpViewController alloc] initWithNibName:@"HelpView" bundle:nil];

以及实际 .xib 文件的名称。

【讨论】:

【参考方案9】:

我认为这个问题与我也遇到的问题有关。 很容易重现:

创建新的 XCode 项目“实用程序”。在 FlipsideViewController.m 您只需插入以下方法:

- (void)viewDidAppear:(BOOL)animated 
  [super viewDidAppear: animated];
  [self showInfo];

如果你这样做,启动应用程序,然后翻转视图将被正确激活 离开。只要你按下翻转视图上的“完成”按钮,你就会回来 到 Mainview 再次触发 viewDidAppear 并直接返回到另一面- 看法。一旦显示翻转视图,应用程序就会停止 - 没有内存 释放分配器被调用——就像你按下了主页按钮一样。

当我在这些视图中使用一些附加属性时,我也遇到了异常, 所以我将代码精简到最低限度......

我真的不知道,这个问题到底是什么......

最好的问候, 托比亚斯

【讨论】:

【参考方案10】:

这真的取决于viewDidAppear 的支持例程正在做什么。例如,如果presentModalViewController:animated: 不保留loader,则崩溃可能是由于UIWindowController 试图谈论已发布的loader(在您发布的例程末尾)。

【讨论】:

感谢您的评论。我已经尝试将它存储在一个实例变量中,所以它肯定会被保留,但我仍然收到错误。 这里有两个视图——一个进来一个出去——你是否保留这两个视图直到转换完成?在那之前保持两个视图都存在可能存在问题。【参考方案11】:

在使用与您相同的技术来实现加载视图时,我遇到了类似的问题。当加载视图在加载结束时被关闭时,它会崩溃。 在我的情况下,问题来自这样一个事实,即一旦加载视图被关闭,viewDidAppear 就会再次被调用并试图再次呈现加载视图,这可能触发了崩溃。 我只是通过检查加载视图之前是否出现过来修复它:

- (void)viewDidAppear:(BOOL)animated 
    [super viewDidAppear:animated];

    if(needDisplayLoader)
        [self presentModalViewController: loader animated:NO];

然后我在关闭加载器视图之前将 needDisplayLoader 设置为 NO

希望这会有所帮助...

【讨论】:

【参考方案12】:

我刚才遇到了这个问题,并使用上面的 selector:afterDelay 建议进行了更正。补充一下,我在 iPhone OS 4.0 beta 下编译(没有修复),没有崩溃!因此,XCode 中的错误似乎已在下一代中得到修复。并不是说这对我们今天的任何人有任何好处,但是,正如你们都知道的那样,这确实是 Xcode 中的一个错误,而不一定是我们在编码风格中做错了什么。

【讨论】:

【参考方案13】:

有完全相同的问题。用上面的建议解决了...

[self performSelector:@selector(doit) withObject:nil afterDelay:0.5];

必须使用 0.5 秒的延迟。可能是因为我在 UIPickerViewController 模态之后直接执行 presentModalViewController。

【讨论】:

【参考方案14】:

我刚遇到这个问题,结果发现我的问题是因为我解除了我的协议委托。

【讨论】:

【参考方案15】:

我认为循环的原因是你正在加载的新视图控制器默认有一个 viewDidAppear 方法,它有

[super viewDidAppear animated];

这意味着它将再次回调主视图控制器的 viewDidAppear,就像它会循环一样

在你展示的 Viewcontroller 中有这样的方法,没有超级 viewdidapper:

-(void)viewDidAppear:(BOOL)animated
    //[super viewDidAppear:animated]; no super


【讨论】:

【参考方案16】:

EXC_BAD_ACCESS 是内存错误。您可能正在尝试使用已经释放/释放的对象。这个答案提供了一些调试这些问题的提示:

Debugging EXC_BAD_ACCESS

【讨论】:

我在一个最小的测试应用程序中遇到了完全相同的问题,我知道这不是正常的内存管理问题。

以上是关于呈现模态视图控制器时 iPhone 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 10 中以模态方式呈现新 VC 时崩溃

iOS UISearchController 崩溃:应用程序试图在自身上呈现模态视图控制器

在不覆盖 iPhone 上的当前视图的情况下呈现模态视图控制器

模态视图控制器关闭时应用程序崩溃

应用程序不会以模态方式呈现,但崩溃与`应用程序试图以模态方式呈现活动控制器`

无法在标签栏控制器的顶部完全呈现模态视图控制器