Get HTML from WKWebview in Swift
I was here to try to get clues about getting result after asking token form DROPBOX new APIS. (I am implementing their flow WITHOUT all the stuff of their SDK) Hope can help someone.
Now Dropbox uses a web page as login, and calls back YOUR url where You can process token.
import WebKit
import SwiftUI
// some code from:
// https://benoitpasquier.com/create-webview-in-swiftui/
// THX pasquier!
let APP_KEY = "YOUR APP KEY"
let REDIRECT_URI = "<YOUR SITE>.dropbox_auth.php"
let DB_URL = "https://www.dropbox.com/1/oauth2/authorize?client_id=APP_KEY&token_access_type=offline&response_type=code&redirect_uri=REDIRECT_URI"
class MyWKDelegate: NSObject, WKNavigationDelegate{
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("End loading")
webView.evaluateJavaScript("document.body.innerHTML", completionHandler: { result, error in
if let html = result as? String {
print(html)
}
})
}
}
struct WebView: UIViewRepresentable {
typealias UIViewType = WKWebView
let webView: WKWebView
func makeUIView(context: Context) -> WKWebView {
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) { }
}
class WebViewModel: ObservableObject {
let webView: WKWebView
let url: URL!
let delegate = MyWKDelegate()
init() {
webView = WKWebView(frame: .zero)
webView.navigationDelegate = delegate
let urlStr = DB_URL.replacingOccurrences(of: "APP_KEY", with: APP_KEY).replacingOccurrences(of: "REDIRECT_URI", with: REDIRECT_URI)
print(urlStr)
url = URL(string: urlStr)
loadUrl()
}
func loadUrl() {
webView.load(URLRequest(url: url))
}
}
If you wait until the page has loaded you can use:
webView.evaluateJavaScript("document.documentElement.outerHTML.toString()",
completionHandler: { (html: Any?, error: Error?) in
print(html)
})
You could also inject some javascript that returns you back the HTML.
let script = WKUserScript(source: javascriptString, injectionTime: injectionTime, forMainFrameOnly: true)
userContentController.addUserScript(script)
self.webView.configuration.userContentController.addScriptMessageHandler(self, name: "didGetHTML")
…
func userContentController(userContentController: WKUserContentController,
didReceiveScriptMessage message: WKScriptMessage) {
if message.name == "didGetHTML" {
if let html = message.body as? String {
print(html)
}
}
}
The javascript you could inject looks something like:
webkit.messageHandlers.didGetHTML.postMessage(document.documentElement.outerHTML.toString());
WKWebView
get HTML from WKWebView
wkWebView.evaluateJavaScript("document.body.innerHTML", completionHandler: { (value: Any!, error: Error!) -> Void in
if error != nil {
//Error logic
return
}
//let result = value as? String
//Main logic
})
set HTML into WKWebView
//Do not forget to extend a class from `WKNavigationDelegate`
func someFunction() {
let wkWebView = WKWebView()
wkWebView.loadHTMLString("<html><body></body></html>", baseURL: nil)
wkWebView.navigationDelegate = self as? WKNavigationDelegate
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
//ready to be processed
}
[get/set HTML from UIWebView]