【问题标题】:iOS WKWebView not showing javascript alert() dialogiOS WKWebView 不显示 javascript alert() 对话框
【发布时间】:2015-01-10 00:16:47
【问题描述】:

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

【问题讨论】:

  • 我也面临同样的问题。我也无法将 safari 检查器连接到我的 ipad,因此我看不到警报或 console.log。这使得 wkwebview 的开发几乎是人间地狱。
  • 你可以尝试托管 html 文件并尝试“http://”而不是“file://”,这可能是因为 wkwebview 中的这个错误:openradar.me/radar?id=5839348817723392
  • html 文件存储在本地,因此可以离线访问。文件加载没有问题,它只是在点击按钮时不显示的警报对话框。

标签: javascript ios wkwebview


【解决方案1】:
  1. 将协议实现到您的 WKWebview 容器控制器。 WKUIDelegate
  2. 将偏好添加到 WKWebview 以在 viewDidLoad() 中启用 javascript。

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

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

【讨论】:

  • 方法签名发生了变化:func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, InitialByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) ...
【解决方案2】:

这是

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

【讨论】:

    【解决方案3】:

    这是 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: {});
    }
    

    【讨论】:

    • 使用未解析的标识符“UIAlertController”。使用 XCode 10.2 和 Swift 5
    【解决方案4】:

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

    【讨论】:

    • 这段代码应该插入到哪里?我将它直接插入class ViewController - 它可以编译,但我的 JS 无法触发prompt()
    • @godblessstrawberry 它应该被插入到你的 WKView 的 uiDelegate (WKUIDelegate) 中,通常是一个实现该协议的视图控制器。
    • @Crashalot:只需更改(preferredStyle:.alert),它就会像魅力一样发挥作用。谢谢。
    • 另外,你需要在你的 viewController 中添加这个:webView.uiDelegate = self;
    • 对于首选样式,使用 UIAlertController.Style.alert 而不是 .actionSheet。
    【解决方案5】:

    要解决此问题,您需要一个 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:^{}];
    }
    

    更多内容请关注Official Documentation

    【讨论】:

    • 看起来这就是问题所在。谢谢!
    • 如果您仍然没有调用此委托函数,请记住尝试其他两个:runJavaScriptConfirmPanelWithMessagerunJavaScriptTextInputPanelWithPrompt。事件取决于警报的类型。
    • 这里有一个很好的样板来实现所有 3 个委托方法:gist.github.com/davbeck/8613f2e74e8fc335c14d
    • 这不适用于 wkwebview 的 evaluateJavaScript(),参考这篇文章stackoverflow.com/q/43600624/6521116
    • 你救了我的命
    【解决方案6】:

    只是为了扩展一点,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];
    }
    

    当然,您可以自行过滤掉错误的警报/确认/提示请求。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多