【问题标题】:What can cause UIAlertController actions to never be called?什么会导致 UIAlertController 操作永远不会被调用?
【发布时间】:2016-03-21 18:44:04
【问题描述】:

在崩溃报告中,我看到 NSInternalInconsistencyExceptionWKWebView 委托方法抛出以提示 JavaScript 警报,即。 “传递给 -[MyClass webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:] 的完成处理程序未被调用”。

每个UIAlertAction 从其处理程序调用WKWebView 完成处理程序。唯一的解释是警报在没有调用任何操作的情况下被取消。 UIAlertView 具有此类情况的委托方法,但 UIAlertController 不提供这种级别的控制。

有没有人为此设计过解决方案?

我考虑过使用 Apple 在 CompletionHandlerCallChecker(在 WebKit 中)中使用的相同技术来捕获我自己的回调未能被调用,并调用 WKWebView 的处理程序来防止虚假异常。看起来非常笨拙,我还不确定它会起作用。我宁愿从一开始就阻止这种情况发生。

编辑:我知道以编程方式关闭警报控制器会产生这种行为,这是不幸的,但我不知道 iOS 决定在没有用户交互的情况下关闭控制器的情况。

编辑2:对于那些请求代码的人来说,这确实是最低限度的实现:

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
  UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
  [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
    completionHandler();
  }]];
  [self presentViewController:alertController animated:YES completion:nil];
}

【问题讨论】:

  • 在您的问题中发布相关代码。
  • 你有一个用于取消按钮的 UIAlertAction 吗?
  • 您找到解决方案了吗?如果没有,您将如何处理您提到的 CompletionHandlerCallChecker?我有完全相同的问题,可能会出现其他一些 UI 并导致警报被解除,而不是被告知只会导致此异常。

标签: ios uialertcontroller wkwebview


【解决方案1】:

这是我的笨拙但有效的解决方案:

class CompletionHandlerCallCheckerDefeater: NSObject {
  private var calledCompletionHandler: Bool = false
  private var fallbackHandler: () -> Void

  init(fallbackHandler: () -> Void) {
    self.fallbackHandler = fallbackHandler
  }

  deinit {
    if (!calledCompletionHandler) {
      fallbackHandler()
    }
  }

  func didCallCompletionHandler() {
    calledCompletionHandler = true
  }
}

在您的委托回调中,像这样使用它:

let defeater = CompletionHandlerCallCheckerDefeater(fallbackHandler: completionHandler)
let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
alertController.addAction(UIAlertAction(title:"OK", style: .Default) { (action) in
    completionHandler()
    defeater.didCallCompletionHandler()
})
presentViewController(alertController, animated: true, completion:  nil)

为fallbackHandler分配任何必要的东西,它不必是传入的块,它只需要使用适当的参数调用completionHandler。 “defeater”在所有引用被释放时销毁,即alert被销毁时,如果没有调用didCallCompletionHandler,它会调用fallbackHandler(调用completionHandler),从而避免异常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    • 2018-11-02
    • 1970-01-01
    相关资源
    最近更新 更多