WKWebView evaluateJavaScript 不返回 html
Posted
技术标签:
【中文标题】WKWebView evaluateJavaScript 不返回 html【英文标题】:WKWebView evaluateJavaScript not returning html 【发布时间】:2017-04-02 16:34:28 【问题描述】:我正在尝试使用 evaluatejavascript 解析从 WKWebView load() 返回的 html,但它从不打印任何内容。我这样做对吗?还有其他方法吗? didFinish 确实打印了。
import UIKit
import WebKit
class MyWebViewController: UIViewController, WKNavigationDelegate
var webView: WKWebView!
override func viewDidLoad()
super.viewDidLoad()
webView = WKWebView(frame: self.view.frame)
webView.navigationDelegate = self
let url = NSURL (string: "https://google.com");
let request = NSURLRequest(url: url! as URL)
webView.load(request as URLRequest)
self.view.addSubview(webView)
self.view.sendSubview(toBack: webView)
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)
webView.evaluateJavaScript("document.documentElement.outerHTML.toString()", completionHandler: (html: AnyObject?, error: NSError?) in
print(html!)
as? (Any?, Error?) -> Void)
print("didFinish")
【问题讨论】:
【参考方案1】:将evaluateJavaScript
与WKWebView
一起使用有点棘手。
由于我认为这个答案对很多人都有用,而不是用简短的代码 sn-p 和您需要实现 WKScriptMessageHandler
的评论来解决您的具体问题,我将发布一个完整的、完整的示例,您可以使用该示例查看所有内容如何协同工作。
要使用它,请在 Xcode 中创建一个“单一视图应用程序”ios 项目并将其粘贴到默认的 ViewController.swift
文件上。
//
// WebViewController.swift
// WKWebViewExample
//
// Created by par on 4/2/17.
// Copyright © 2017 par. All rights reserved. MIT License.
//
import UIKit
import WebKit
class ViewController: UIViewController
override func viewDidLoad()
super.viewDidLoad()
let webViewController = WebViewController()
// install the WebViewController as a child view controller
addChildViewController(webViewController)
let webViewControllerView = webViewController.view!
view.addSubview(webViewControllerView)
webViewControllerView.translatesAutoresizingMaskIntoConstraints = false
webViewControllerView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
webViewControllerView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
webViewControllerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
webViewControllerView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
webViewController.didMove(toParentViewController: self)
class WebViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler
private var webView: WKWebView!
private var webViewContentIsLoaded = false
init()
super.init(nibName: nil, bundle: nil)
self.webView =
let contentController = WKUserContentController()
contentController.add(self, name: "WebViewControllerMessageHandler")
let configuration = WKWebViewConfiguration()
configuration.userContentController = contentController
let webView = WKWebView(frame: .zero, configuration: configuration)
webView.scrollView.bounces = false
webView.navigationDelegate = self
return webView
()
required init?(coder aDecoder: NSCoder) fatalError("init(coder:) has not been implemented")
override func viewDidLoad()
super.viewDidLoad()
view.addSubview(webView)
webView.translatesAutoresizingMaskIntoConstraints = false
webView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
webView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
webView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
webView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
if !webViewContentIsLoaded
let url = URL(string: "https://***.com")!
let request = URLRequest(url: url)
webView.load(request)
webViewContentIsLoaded = true
private func evaluateJavascript(_ javascript: String, sourceURL: String? = nil, completion: ((_ error: String?) -> Void)? = nil)
var javascript = javascript
// Adding a sourceURL comment makes the javascript source visible when debugging the simulator via Safari in Mac OS
if let sourceURL = sourceURL
javascript = "//# sourceURL=\(sourceURL).js\n" + javascript
webView.evaluateJavaScript(javascript) _, error in
completion?(error?.localizedDescription)
// MARK: - WKNavigationDelegate
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)
// This must be valid javascript! Critically don't forget to terminate statements with either a newline or semicolon!
let javascript =
"var outerHTML = document.documentElement.outerHTML.toString()\n" +
"var message = \"type\": \"outerHTML\", \"outerHTML\": outerHTML \n" +
"window.webkit.messageHandlers.WebViewControllerMessageHandler.postMessage(message)\n"
evaluateJavascript(javascript, sourceURL: "getOuterHMTL")
// MARK: - WKScriptMessageHandler
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
guard let body = message.body as? [String: Any] else
print("could not convert message body to dictionary: \(message.body)")
return
guard let type = body["type"] as? String else
print("could not convert body[\"type\"] to string: \(body)")
return
switch type
case "outerHTML":
guard let outerHTML = body["outerHTML"] as? String else
print("could not convert body[\"outerHTML\"] to string: \(body)")
return
print("outerHTML is \(outerHTML)")
default:
print("unknown message type \(type)")
return
【讨论】:
您不认为这会在代码中添加额外的文件,并且在项目成本基于 LoC 时可能不是首选。无论如何+1! 很好的答案有效,帮助我登录到我需要的网络。问题,然后在这个站点登录后出现另一个网页,我需要在那里运行一个javascript,输入姓氏并返回?想法在哪里/如何做到这一点?你可以给我发电子邮件是最好的。谢谢迈克 嗨@Mike - 我担心你的问题对于 cmets 中的答案来说太复杂了,并且对于这个特定的问题和答案来说并不是真正的主题。很大程度上取决于登录后出现的网页以及如何与之交互。我建议您在 *** 上提出一个新问题,并向人们展示您迄今为止的想法。希望您能得到许多有用的答案!【参考方案2】:我知道已经有一段时间没有回答这个问题了,我发现这对我来说真的不起作用。我改用下面的。
在添加 setTimeout() 函数之前,我无法让 evaluateJavaScript 工作。值得一提的是我的代码如下。
webView.evaluateJavaScript("setTimeout(function()
// Do something here
,10);") (result1, error) in
if error == nil
print(result1 ?? "")
【讨论】:
以上是关于WKWebView evaluateJavaScript 不返回 html的主要内容,如果未能解决你的问题,请参考以下文章