Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS WKWebView not showing javascript alert() dialog

I am having some trouble getting a WKWebView in iOS 8 to display an alert dialog that is called from Javascript. After creating a standard WKWebView and loading an HTML file, I have a button on the page that creates a simple alert with some text. This works in UIWebView and in Google Chrome/Safari, but does not appear to be working in WKWebView. Any help is appreciated.

My setup is as follows:

WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.allowsInlineMediaPlayback = YES;
config.mediaPlaybackRequiresUserAction = false;
_wkViewWeb = [[WKWebView alloc] initWithFrame:_viewWeb.frame config];
_wkViewWeb.scrollView.scrollEnabled = NO;
NSString *fullURL = @"file://.../TestSlide.html";
NSURL *url = [NSURL URLWithString:fullURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10];

[_wkViewWeb loadRequest:request];

The html has the following function:

<SCRIPT Language="JavaScript">
function alertTest() {
    alert("Testing Alerts");
}
</SCRIPT>

And a button:

<b>Test Alerts: <input type="button" value="Alert Popup" onclick="alertTest()"><br></b> <br>

This setup works in UIWebView and in regular browsers, but does not work in WKWebView. Am I missing something in the configuration? Should I be using one of the WK delegates to control the alert/confirm dialog behavior? Thank you.

like image 587
Charlie Avatar asked Nov 12 '14 23:11

Charlie


People also ask

How do I display JavaScript alerts in a UWP message dialog?

This platform-specific enables a WebView to display JavaScript alerts in a UWP message dialog. It's consumed in XAML by setting the WebView.IsJavaScriptAlertEnabled attached property to a boolean value: Alternatively, it can be consumed from C# using the fluent API:

Can you use JavaScript dialogs in iOS Safari?

The Apple iOS Safari documentation also states you can can create JavaScript dialogs with the JavaScript alert, confirm, and prompt dialog methods. When you use these JavaScript dialog methods, iOS displays an attractive dialog over your web page that looks like a native iPhone or iPad dialog.

What does the iPhone JavaScript confirm dialog look like?

And here's what the iPhone JavaScript confirm dialog looks like when the "click me" link is clicked: As you can see, the iPhone JavaScript confirm dialog looks just like a regular iPhone dialog. Finally, this HTML and JavaScript source code:

How do I open a JavaScript window in iOS Safari?

According to Apple's iOS Safari web documentation, you can use "iPhone JavaScript windows and dialogs" that are supported by iOS. Here's how. You can create a new iPhone/iPad iOS Safari window by invoking the JavaScript window.open () method. As a word of caution, Apple's documentation provides this note:


3 Answers

To solve this you need a WKUIDelegate for your web view. It is the duty of the delegate to decide if an alert should be displayed, and in what way. You need to implement this for alert, confirm and text input (prompt).

Here is sample code without any validation of the page url or security features:

- (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:^{}];
}

More in the Official Documentation

like image 160
Nikola Lajic Avatar answered Oct 20 '22 02:10

Nikola Lajic


Swift 3 with all 3 optional functions implemented:

func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo,
             completionHandler: @escaping () -> Void) {

    let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)
    alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
        completionHandler()
    }))

    present(alertController, animated: true, completion: nil)
}


func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo,
             completionHandler: @escaping (Bool) -> Void) {

    let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet)

    alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
        completionHandler(true)
    }))

    alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
        completionHandler(false)
    }))

    present(alertController, animated: true, completion: nil)
}


func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo,
             completionHandler: @escaping (String?) -> Void) {

    let alertController = UIAlertController(title: nil, message: prompt, preferredStyle: .actionSheet)

    alertController.addTextField { (textField) in
        textField.text = defaultText
    }

    alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
        if let text = alertController.textFields?.first?.text {
            completionHandler(text)
        } else {
            completionHandler(defaultText)
        }
    }))

    alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in
        completionHandler(nil)
    }))

    present(alertController, animated: true, completion: nil)
}
like image 25
Crashalot Avatar answered Oct 20 '22 02:10

Crashalot


Just to expand a bit, WKWebView requires you to show alerts, prompts, and confirms yourself. Do this by becoming a WKUIDelegate:

#import <WebKit/WebKit.h>
@interface MyController : UIViewController<WKUIDelegate>

Then assign the delegate:

web.UIDelegate = self;

Then you need to actually implement alert, prompt, and confirm. I create WKWebViewPanelManager.h/m as an easy implementation, so here's what I do:

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
    [WKWebViewPanelManager presentAlertOnController:self.view.window.rootViewController title:@"Alert" message:message handler:completionHandler];
}

- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler {
    [WKWebViewPanelManager presentConfirmOnController:self.view.window.rootViewController title:@"Confirm" message:message handler:completionHandler];
}

- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler {
    [WKWebViewPanelManager presentPromptOnController:self.view.window.rootViewController title:@"Prompt" message:prompt defaultText:defaultText handler:completionHandler];
}

Of course, it's up to you to filter out bad alert/confirm/prompt requests.

like image 21
bendytree Avatar answered Oct 20 '22 01:10

bendytree