WKWebView completionHandler 在解雇前调用

WKWebView completionHandler called before dismissal

我正在使用 WKUIDelegate 这个函数来处理 javascript 警报

-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{

    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Test Alert", nil)
                                                     message:message
                                                    delegate:self
                                           cancelButtonTitle:nil
                                           otherButtonTitles:@"OK", nil] autorelease];

    [alert show];
    completionHandler();
}

根据 Apple 文档,我们应该在按下 OK 按钮后调用警报的 compeletionHandler(),如前所述 here

按下OK按钮后如何调用completionHandler()?如果我不调用 completionHandler() 期望被抛出

**[WKWebViewController webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:
    completionHandler:]:
***** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
   reason: 'Completion handler passed to -[WKWebViewController
   webView:runJavaScriptAlertPanelWithMessage:
   initiatedByFrame:completionHandler:] was not called'****

更新:

Stefan 在下面提到的解决方案在 JS Alert 上运行良好,但在 JS Confirm 上运行不佳。以下是我得到相同异常的代码,即使在确定和取消按钮中调用了 completionHandler()。

-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler
{
    MKCLOG_DEBUG(@"%@", frame.request.URL);
    UIAlertController* alert = [UIAlertController alertControllerWithTitle:
                                NSLocalizedString(@"Test", nil) message: message
                                                            preferredStyle: UIAlertControllerStyleAlert];

    UIAlertAction *cancelAction = [UIAlertAction
                                   actionWithTitle:NSLocalizedString(@"Cancel", @"")
                                   style:UIAlertActionStyleCancel
                                   handler:^(UIAlertAction *action)
                                   {
                                       MKCLOG_DEBUG(@"Cancel action");
                                       completionHandler(NO);
                                   }];

    UIAlertAction *okAction = [UIAlertAction
                               actionWithTitle:NSLocalizedString(@"OK", @"OK action")
                               style:UIAlertActionStyleDefault
                               handler:^(UIAlertAction *action)
                               {
                                   MKCLOG_DEBUG(@"OK action");
                                   completionHandler(YES);
                               }];

    [alert addAction:cancelAction];
    [alert addAction:okAction];
}

您现在的代码设置方式,您立即显示 UIAlertView 运行 completionHandler()。两者同时发生。

你应该做的是这样的:

UIAlertController* alert = [UIAlertController alertControllerWithTitle:
    NSLocalizedString(@"Test Alert", nil) message: message
        preferredStyle: UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle: @"OK"
    style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
      completionHandler();
}]; 
[alert addAction:defaultAction];
[self presentViewController:alert animated:YES completion:nil];

这将显示警报并在用户关闭时调用 completionHandler

请注意,我使用的是 UIAlertController,它仅适用于 iOS 8 及更高版本,但应该没问题,因为您依赖于 WKWebView.