Подтвердить что ты не робот

WKWebView - подтверждение и предупреждение Javascript не работают

Я использую WKWebView, чтобы открыть example.com, и там у меня есть тестовая ссылка, которая должна открыть оповещение JS, но я не могу ее отобразить на устройстве, она работает только если я просмотрите сайт из браузера.

Я использую WKUIDelegate и добавил этот фрагмент кода в файл ViewController.swift:

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

    NSLog("Hello")
}

Я ничего не вижу в консоли XCode, когда я нажимаю ссылку, которая порождает предупреждение JS.

Что мне не хватает?

4b9b3361

Ответ 1

Вам также нужно установить uiDelegate в WKWebView.

import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {

    var wkWebView: WKWebView!

    public override func viewDidLoad() {
        super.viewDidLoad()

        wkWebView = WKWebView(frame: view.bounds, configuration: WKWebViewConfiguration())
        wkWebView.uiDelegate = self
        wkWebView.navigationDelegate = self
        view.addSubview(wkWebView!)
        let url = URL(string: "https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_alert")!
        wkWebView.load(URLRequest(url: url))
    }

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

        let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
        let title = NSLocalizedString("OK", comment: "OK Button")
        let ok = UIAlertAction(title: title, style: .default) { (action: UIAlertAction) -> Void in
            alert.dismiss(animated: true, completion: nil)
        }
        alert.addAction(ok)
        present(alert, animated: true)
        completionHandler()
    }

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        wkWebView.evaluateJavaScript("alert('Hello from evaluateJavascript()')", completionHandler: nil)
    }
}

Для confirm() и prompt() см. другие методы делегата.

Ответ 2

Немного поздно, но я хотел бы добавить свой опыт для дальнейшего использования. Ответ @Bon Bon привел меня к пути к решению, когда я пытался заставить вещи работать с Swift 3 и IOS 10, и в этом случае код нуждается в некоторых модификациях. Во-первых, вам нужно также реализовать WKUIDelegate, поэтому добавьте его в объявление ViewController:

class ViewController: UIViewController, WKUIDelegate {

Затем, когда вы создаете экземпляр объекта WKWebView, как, например, так:

self.webView = WKWebView(frame: self.view.frame)

вам также необходимо присвоить правильное значение свойству uiDelegate экземпляра:

self.webView?.uiDelegate = self

Затем, наконец, вы можете использовать код, предоставленный @Bon Bon, но обратите внимание, что Swift 3 требует некоторых небольших отличий, например, имя метода presentViewController становится present:

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

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

    self.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: .alert)

    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)

    }))

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

Это позволило alert, confirmation и text input правильно работать в WKWebView, без предупреждения компилятора в Xcode 8. Я не опытный программист Swift, поэтому любые полезные комментарии о правильности кода будут очень благодарны.

Ответ 3

Вот пример кода для реализации различных предупреждений javascript в Swift:

Все о преобразовании информации в предупреждение javascript в собственный пользовательский интерфейс и вызовите функцию завершенияHandler(), чтобы отправить действие пользователя обратно в механизм JavaScript.

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

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

        alertController.addAction(UIAlertAction(title: "Ok", style: .Default, handler: { (action) in
            completionHandler()
        }))

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

func webView(webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: (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)
        }))

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

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

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

        alertController.addTextFieldWithConfigurationHandler { (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)

        }))

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