试图用未知的演示者解除 UIAlertController
Posted
技术标签:
【中文标题】试图用未知的演示者解除 UIAlertController【英文标题】:Trying to dismiss UIAlertController with unknown presenter 【发布时间】:2015-04-15 11:38:56 【问题描述】:我的应用程序崩溃了,一定是因为 UIAlertController。
此问题仅在 UIAlertController 可用的 ios 8.x 上发生。奇怪的事实是我的应用程序既不使用 UIAlertViewController 也不使用 UIAlertView。
报告告诉我:
Trying to dismiss UIAlertController <UIAlertController: 0x172c5d80> with unknown presenter.
这怎么会发生?
我想过
-
由于摇晃手势而显示的 System AlertView 撤消
当提示或通用对话框仍在屏幕上时,WebView 被释放
低电量警报
但没有一个案例让我陷入崩溃。
崩溃日志对我的建议是,操作系统显示了一个 AlertView,它将附加到我的应用程序窗口,并且在某些情况下会丢失显示 UIAlertViewController 的父视图控制器。
任何想法如何找到问题?
这里是堆栈跟踪
_________________________________
0 CoreFoundation 0x2bc0c45f __exceptionPreprocess + 127
1 libobjc.A.dylib 0x39c79c8b objc_exception_throw + 36
2 CoreFoundation 0x2bc0c3a5 +[NSException raise:format:] + 110
3 UIKit 0x2f4ad13d -[UIAlertController _dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:] + 414
4 UIKit 0x2f4acf97 -[UIAlertController _dismissAnimated:triggeringAction:] + 28
5 UIKit 0x2f590a0b -[_UIAlertControllerActionView touchesEnded:withEvent:] + 160
6 UIKit 0x2f159567 -[UIWindow _sendTouchesForEvent:] + 520
7 UIKit 0x2f152e31 -[UIWindow sendEvent:] + 542
8 UIKit 0x2f129759 -[UIApplication sendEvent:] + 194
9 UIKit 0x2f39d2f9 _UIApplicationHandleEventFromQueueEvent + 14166
10 UIKit 0x2f1281a9 _UIApplicationHandleEventQueue + 1350
11 CoreFoundation 0x2bbd2fbf __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 12
12 CoreFoundation 0x2bbd23cf __CFRunLoopDoSources0 + 216
13 CoreFoundation 0x2bbd0a35 __CFRunLoopRun + 770
14 CoreFoundation 0x2bb1e3b1 CFRunLoopRunSpecific + 474
15 CoreFoundation 0x2bb1e1c3 CFRunLoopRunInMode + 104
16 GraphicsServices 0x3308d201 GSEventRunModal + 134
17 UIKit 0x2f18843d UIApplicationMain + 1438
18 MyApp 0x00028a07 main (main.mm:16)
编辑
holes 询问我的窗口初始化。这是我的 AppDelegate 的代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
self.window = [[MyAppCustomWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
_mainViewController = [[MyAppContainerViewController alloc] initWithNibName:nil bundle:nil];
_mainStatusBarVC = [[MyAppStatusBarVC alloc] initWithRootVC:_mainViewController];
[self.window setRootViewController:_mainStatusBarVC];
[self.window makeKeyAndVisible];
return YES;
【问题讨论】:
您是如何为您的应用初始化UIWindow
实例的?
我在我的 AppDelegate 应用程序中初始化了 MyCustomWindow:didFinishLaunchingWithOptions: 然后我设置了 rootViewController 并使用 self.window makeKeyAndVisible 使其成为键和可见。我将用一些关于它的代码来编辑问题。
添加了有关 MyCustomWindow 初始化的代码。我有兴趣重现该问题,以确保任何类型的代码修复都可以肯定地解决该问题。我不知道为什么 UIAlertViewController 会显示在我的应用程序堆栈跟踪中。
从你的介绍中我看不出来。一定是有其他原因造成的。
完全正确...我错过了显示此系统警报的内容。必须是一个以某种方式干扰我的应用程序的系统进程,但我无法弄清楚。
【参考方案1】:
我打赌你的崩溃发生在 iPad 上。
在 iPad 上,从 iOS8 开始,UIActionSheet 似乎使用UIAlertController
处理
使用此代码,
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
if(buttonIndex == 1) return; // Cancel button
[self doSomeViewControllerDismisses];
我的应用因与您遇到的相同错误而崩溃。
为了防止这种情况,我只是在下一次 MainThread 执行时调度复杂的解除调用,给隐藏的UIAlertViewController
正确释放的机会。
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
if(buttonIndex == 1) return; // Cancel button
dispatch_async(dispatch_get_main_queue(), ^
[self doSomeViewControllerDismisses];
);
【讨论】:
感谢马丁的提示。不幸的是,我的应用根本不使用 UIActionSheet 您的应用是否使用弹出框 (UIPopoverController
)?我认为 Apple 开发人员在其他几个 UIKit 控件中重用了这个 UIAlertController
,比如弹出框。
是的,我使用它。我会检查的。【参考方案2】:
此表单的堆栈跟踪通常表明您已离开 UIViewController,而您拥有它的警报仍在解除。
解决这个问题的一般方法是在 UIAlertViewDelegate 的 alertView:didDismissWithButtonIndex: 方法中显示或关闭控制器,这样您就可以确定在任何关闭期间演示者都不会离开。
在您的情况下,如果您找不到任何可重现的情况,您可以尝试在呈现/关闭控制器之前检查presentedViewController,看看是否有任何问题。
但是,如果您审核控制器转换,您可能会发现响应系统警报的某个地方可能会以编程方式触发导航。您是否有任何功能会为用户授权引发系统警报,例如访问照片或其他任何内容,并且他们否认它会导致控制器被您的错误处理以编程方式解雇?这似乎是一个相当合理的场景。
【讨论】:
正如我所写的,我的整个代码根本不使用 UIAlertViewController。我无法访问源代码的唯一第三方库是批评。我实验过,在同样的情况下,不知道何时,crittercism 会向用户发出位置跟踪确认警报。因为我不知道 Crittercism 库何时尝试访问它,所以我自己尝试模拟 crittercism 可能的 LocationManager 所有权,如下一条评论中所述。 MyAppDelegate 保留 locationManager,而模态呈现的 viewController 请求授权使用位置功能。这会导致显示系统跟踪警报。现在我可以通过我的应用程序上可用的远程功能来关闭模态控制器。这将导致模式视图控制器在跟踪警报仍在屏幕上时关闭。点击警报、取消或允许的两个按钮中的任何一个,我的应用程序仍然可以运行,没有任何不良后果。 无论如何,根据您的回答,我还有另一个问题。您确定使用显示系统弹出窗口的 iOS SDK API,作为位置跟踪或照片访问,我可以在当前显示的视图控制器上找到 UIViewController 检查presentedViewController 吗?我不这么认为......我现在没有测试它,但我觉得很奇怪,我必须在自己的代码中关心 iOS 自己生成的东西。当然,这可能是 iOS 8 的错误,但如果我感到惊讶的是,我在使用 iOS 8 的 iOS 设备上运行的数千个应用程序中从未遇到过它。 在任何正常情况下,都不应该。但是,由于您很确定崩溃的警报控制器不是您的,所以我对它如何生成所提供的崩溃日志的“合理合理”的猜测是,它变得混乱并使用您的一个控制器消失了,而不是无论它应该呈现什么。【参考方案3】:尝试使用 Block on main thrad 在主线程 Alertview 上关闭。
dispatch_async(dispatch_get_main_queue(), () -> Void in
// Write your alert view code in swift language .
)
【讨论】:
问题是,如果 myApp 根本不使用 UIAlertController,myApp 怎么会在 UIAlertController 上崩溃……以上是关于试图用未知的演示者解除 UIAlertController的主要内容,如果未能解决你的问题,请参考以下文章
Android MVP - 应该避免在演示者中使用 R.string 引用吗?
应该将演示者(mvP)注入(dagger2)到android中的视图吗?