WKWebView 遇到 NSInternalInconsistencyException runJavaScriptAlertPanelWithMessage: was not called
Completion handler passed to -[xxx.BaseWebViewController webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:] was not called
從 crash 可以看出是 WKWebView 回調(diào)函數(shù): runJavaScriptAlertPanelWithMessage中completionHandler 沒有被調(diào)用導(dǎo)致的。
出現(xiàn)情況可能是WKWebView 退出的時候筹误,JS剛好執(zhí)行了window.alert(), alert 框可能彈不出來桐早,completionHandler 最后沒有被執(zhí)行,導(dǎo)致 crash厨剪;另一種情況是在 WKWebView 一打開哄酝,JS就執(zhí)行window.alert(),這個時候由于 WKWebView 所在的 UIViewController 出現(xiàn)(push或present)的動畫尚未結(jié)束祷膳,alert 框可能彈不出來陶衅,completionHandler 最后沒有被執(zhí)行,導(dǎo)致 crash直晨。
解決辦法如下:
#pragma mark -- WKUIDelegate
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
if ([self.navigationController visibleViewController] != self)
{
completionHandler();
return;
}
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:message preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"確認" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
completionHandler();
}]];
if ([self.navigationController visibleViewController] == self) {
[self presentViewController:alertController animated:YES completion:nil];
}else
{
completionHandler();
}
}
// 顯示兩個按鈕搀军,通過completionHandler回調(diào)判斷客戶點擊確實定還是取消按鈕
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler{
if ([self.navigationController visibleViewController] != self) {
completionHandler(NO);
return;
}
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
completionHandler(YES);
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
completionHandler(NO);
}]];
if ([self.navigationController visibleViewController] == self) {
[self presentViewController:alertController animated:YES completion:nil];
}else{
completionHandler(NO);
}
}
// 顯示一個帶有輸入框和一個確定按鈕的,通過completionHandler回調(diào)客戶輸入的內(nèi)容
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{
if ([self.navigationController visibleViewController] != self) {
completionHandler(@"error");
return;
}
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"" message:nil preferredStyle:UIAlertControllerStyleAlert];
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
}];
[alertController addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
completionHandler(alertController.textFields.lastObject.text);
}]];
if ([self.navigationController visibleViewController] == self) {
[self presentViewController:alertController animated:YES completion:nil];
}
else
{
completionHandler(@"error");
}
}