iOS WKWebView 不显示 javascript alert() 对话框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26898941/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 23:29:56  来源:igfitidea点击:

iOS WKWebView not showing javascript alert() dialog

javascriptioswkwebview

提问by Charlie

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.

我在 iOS 8 中获取 WKWebView 以显示从 Javascript 调用的警报对话框时遇到了一些麻烦。创建标准 WKWebView 并加载 HTML 文件后,我在页面上有一个按钮,用于创建带有一些文本的简单警报。这适用于 UIWebView 和 Google Chrome/Safari,但似乎不适用于 WKWebView。任何帮助表示赞赏。

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:

html具有以下功能:

<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.

此设置适用于 UIWebView 和常规浏览器,但不适用于 WKWebView。我在配置中遗漏了什么吗?我应该使用 WK 代表之一来控制警报/确认对话框行为吗?谢谢你。

回答by Nikola Lajic

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).

为了解决这个问题,您需要一个 WKUIDelegate 用于您的 Web 视图。代表有责任决定是否应显示警报以及以何种方式显示。您需要为警报、确认和文本输入(提示)实现此功能。

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

这是没有对页面 url 或安全功能进行任何验证的示例代码:

- (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

更多官方文档

回答by Crashalot

Swift 3with all 3 optional functions implemented:

Swift 3 实现了所有 3 个可选功能:

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)
}

回答by bendytree

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

只是稍微扩展一下,WKWebView需要您显示警报、提示和确认自己。通过成为一个来做到这一点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/mas an easy implementation, so here's what I do:

那么就需要实际实现alert、prompt、confirm。我创建WKWebViewPanelManager.h/m作为一个简单的实现,所以这就是我要做的:

- (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.

当然,过滤掉错误的警报/确认/提示请求取决于您。

回答by Stafford Williams

And here's that in swift:

这是swift 中的

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

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

    alertController.addAction(UIAlertAction(title: "OK", style: .cancel) {
        _ in completionHandler()}
    )

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

回答by Muhammad Maqsood

  1. Implement the protocol to your WKWebview container controller. WKUIDelegate
  2. Add preference to WKWebviewto enable javascript in viewDidLoad()as.

    // enable JS
    webView.configuration.preferences.javaScriptEnabled = true
    
  3. Register WKWebviewUI Delegate in viewDidLoad()as

    self.webView.uiDelegate = self
    
  4. Implement the below delegate in your class.

    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: 
    String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> 
    Void) {
    let alertController = UIAlertController(title: message,message: nil,preferredStyle: 
    .alert)
    
    alertController.addAction(UIAlertAction(title: "OK", style: .cancel) {_ in 
    completionHandler()})
    
    self.present(alertController, animated: true, completion: nil)
    }
    
  1. 将协议实现到您的 WKWebview 容器控制器。WKUID代表
  2. WKWebview添加首选项以在viewDidLoad() 中启用 javascript 。

    // enable JS
    webView.configuration.preferences.javaScriptEnabled = true
    
  3. viewDidLoad() 中注册WKWebviewUI 委托为

    self.webView.uiDelegate = self
    
  4. 在您的班级中实现以下委托。

    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: 
    String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> 
    Void) {
    let alertController = UIAlertController(title: message,message: nil,preferredStyle: 
    .alert)
    
    alertController.addAction(UIAlertAction(title: "OK", style: .cancel) {_ in 
    completionHandler()})
    
    self.present(alertController, animated: true, completion: nil)
    }
    

回答by Hassan Taleb

Here is the code in Swift 4.2

这是Swift 4.2 中的代码

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

    let alertController = UIAlertController(title: message, message: nil,
                                            preferredStyle: UIAlertController.Style.alert);

    alertController.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.cancel) {
        _ in completionHandler()}
    );

    self.present(alertController, animated: true, completion: {});
}