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

IT技术 javascript ios wkwebview
2021-03-06 06:57:37

我在 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 代表之一来控制警报/确认对话框行为吗?谢谢你。

6个回答

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

这是没有对页面 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:^{}];
}

更多官方文档

看起来这就是问题所在。谢谢!
2021-04-19 06:57:37
如果您仍然没有调用此委托函数,请记住尝试其他两个:runJavaScriptConfirmPanelWithMessagerunJavaScriptTextInputPanelWithPrompt该事件取决于警报的类型。
2021-05-01 06:57:37
这不适用于 wkwebview 的评估 JavaScript(),请参阅此帖子stackoverflow.com/q/43600624/6521116
2021-05-08 06:57:37
这里有一个用于实现所有 3 个委托方法的很棒的样板:gist.github.com/davbeck/8613f2e74e8fc335c14d
2021-05-13 06:57:37
你救了我的命
2021-05-14 06:57:37

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)
}
@Crashalot:只需更改(preferredStyle:.alert),它就会像魅力一样工作。谢谢。
2021-04-19 06:57:37
应该在哪里插入此代码?我直接将class ViewController插入- 它编译,但我的 JS 无法触发prompt()
2021-04-21 06:57:37
@godblessstrawberry 它应该插入到您的 WKView 的 uiDelegate (WKUIDelegate) 中,通常是一个实现该协议的视图控制器。
2021-04-23 06:57:37
对于首选样式,请使用 UIAlertController.Style.alert 而不是 .actionSheet。
2021-04-30 06:57:37
此外,您需要将其添加到您的 viewController 中: webView.uiDelegate = self;
2021-05-08 06:57:37

只是稍微扩展一下,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];
}

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

这是在

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() 中注册WKWebview UI 委托

    self.webView.uiDelegate = self
    
  4. 在您的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)
    }
    
方法签名已更改: func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initialByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) ...
2021-05-06 06:57:37