I have set up an API to respond to a POST request. Due to the nature of my app, I need to fulfill this POST request through a WKWebView, as opposed to using URLSession or Alamofire. I plan to use the data POST response body elsewhere in my app.
I was able to successfully construct a post request and load it in the following way:
request = URLRequest(url: previouslyDefinedApiURL)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = previouslyDefinedBodyData
myWebView.load(request)
The code above works perfectly. My web view even displays the correct response from my API.
I implemented the WKNavigationDelegate method to which my code hooks into upon loading the request.
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
if let response = navigationResponse.response as? HTTPURLResponse {
// Somehow get the response body?
}
decisionHandler(.allow)
}
The navigation response is of type URLResponse, which offers no way for extracting the body content of the response, which is a simple JSON. Somthing like the following:
{
status: "SUCCESS",
user_id: 1234,
transition_to: 'tabs'
}
Is there a swifty way of obtaining the response body from the wkwebview up in the native side of the code?
I'm answering my own question because I figured out how to do this on my own. Perhaps my question wasn't clear. My end goal was to extract the body content as a string.
Firstly, I ditched the callback I used:
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
// do stuff
}
And instead, I used this callback and executed some javascript on the result:
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.evaluateJavaScript("document.getElementById(\"my-id\").innerHTML", completionHandler: { (jsonRaw: Any?, error: Error?) in
guard let jsonString = jsonRaw as? String else { return }
let json = JSON(parseJSON: jsonString)
// do stuff
})
}
The id "my-id" comes from the response I constructed on the back end of this service, just in case the web view wrapped any other HTML around my response. My original intention was to do this without having to run any javascript, but I guess there's no other way. This works pretty well anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With