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.
Что мне не хватает?
Ответы
Ответ 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)
}