I am using WKUIDelegate this function to handle javascript alert
-(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();
}
According to Apple documentation we should call compeletionHandler() of an alert after OK button is pressed on alert as mentioned here
How to call completionHandler() after press OK button is pressed? If I don't call completionHandler() expection is thrown
**[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'****
UPDATE:
The solution mentioned below by Stefan is working fine with JS Alert but not with JS Confirm. Following is the code I get same exception even if the completionHandler() is called in ok and cancel button.
-(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];
}
The way your code is setup now, you display the UIAlertView
and immediately run the completionHandler()
. Both happen at the same time.
What you should do instead is something like this:
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];
This will present the alert and call the completionHandler
when the user dismisses it.
Note that I am using the UIAlertController
, which is only available on iOS 8 and up, but that should be fine since you depend on WKWebView
.