75

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

我的设置如下:

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];

该html具有以下功能:

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

还有一个按钮:

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

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

4

6 回答 6

89

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

于 2014-11-21T17:39:10.153 回答
56

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)
}
于 2016-10-29T06:00:12.007 回答
21

只是为了扩展一点,WKWebView需要您显示警报、提示并确认自己。通过成为WKUIDelegate

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

然后分配委托:

web.UIDelegate = self;

然后你需要实际实现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];
}

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

于 2015-11-04T20:24:53.057 回答
16

这就是

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)
}
于 2016-03-10T09:19:28.997 回答
7
  1. 将协议实现到您的 WKWebview 容器控制器。WKUIDelegate
  2. 将首选项添加到WKWebview以在viewDidLoad()中启用 javascript 。

    // enable JS
    webView.configuration.preferences.javaScriptEnabled = true
    
  3. 在viewDidLoad()中注册WKWebview UI Delegate为

    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)
    }
    
于 2019-09-01T10:01:50.333 回答
6

这是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: {});
}
于 2018-09-23T09:27:12.013 回答