web-dev-qa-db-fra.com

WKWebView - La confirmation Javascript et l'alerte ne fonctionnent pas

J'utilise WKWebView pour ouvrir example.com, et là-bas, j'ai un lien de test qui est censé ouvrir une alerte JS, mais je ne peux pas le faire s'afficher sur l'appareil, cela ne fonctionne que si je consulte le site depuis le navigateur.

J'utilise WKUIDelegate et j'ai ajouté ce morceau de code au fichier ViewController.Swift:

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

    NSLog("Hello")
}

Je ne vois rien dans la console XCode lorsque je clique sur le lien qui génère l'alerte JS.

Qu'est-ce que je rate?

15
Mike Purcell

Un peu en retard mais je voudrais ajouter mon expérience pour référence future. La réponse de @Bon Bon m'a amené sur la voie de la solution alors que j'essayais de faire fonctionner les choses avec Swift et IOS 10, auquel cas le code nécessite quelques modifications. Tout d'abord, vous devez implémenter également WKUIDelegate, alors ajoutez-le à la déclaration ViewController:

class ViewController: UIViewController, WKUIDelegate {

Ensuite, lorsque vous instanciez l'objet WKWebView, comme par exemple comme ceci:

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

vous devez également affecter la valeur correcte à la propriété uiDelegate de l'instance:

self.webView?.uiDelegate = self

Enfin, vous pouvez utiliser le code fourni par @Bon Bon, mais notez qu'il existe quelques petites différences requises par Swift 3, comme par exemple, le nom de la méthode presentViewController devient 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)
}

Cela a fait alert, confirmation et text input pour fonctionner correctement dans WKWebView, sans aucun avertissement du compilateur dans Xcode 8. Je ne suis pas un expert Swift programmeur, donc tout commentaire utile sur l'exactitude du code serait très apprécié.

20
wiredolphin

Vous devez également définir le uiDelegate sur le 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)
    }
}

Pour confirm() et Prompt() voir les autres méthodes déléguées.

16
Onato

Voici un exemple de code pour diverses implémentations d'alertes javascript dans Swift:

Il s'agit de convertir les informations de l'alerte javascript en I native, et d'appeler le complètementHandler () pour renvoyer l'action de l'utilisateur au moteur 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)
}
7
John the Traveler