2017-04-02 52 views
2

我想解析從WKWebView加載()與evaluateJavaScript返回的HTML,但它從不打印任何東西。我做對了嗎?任何其他方式? didFinish確實打印。WKWebView evaluateJavaScript不返回html

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

} 

}

回答

2

使用evaluateJavaScriptWKWebView是有點棘手。

因爲我認爲這個答案對許多人有用,而不是用短代碼段和你需要實現的評論來解決你的具體問題WKScriptMessageHandler,我會發佈一個完整的,完整的例子,你可以用來看看一切如何協同工作。

要使用此功能,請在Xcode中創建一個「Single View Application」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://google.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 
     } 
    } 
}