如何从Swift中的WKWebView获取POST请求正文?

问题描述:

我已经设置了一个API以响应POST请求.由于我的应用程序的性质,我需要通过WKWebView来完成此POST请求,而不是使用URLSession或Alamofire.我计划在应用程序的其他地方使用数据POST响应正文.

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)

上面的代码可以完美地工作.我的网络视图甚至显示来自我的API的正确响应.

The code above works perfectly. My web view even displays the correct response from my API.

我实现了WKNavigationDelegate方法,在加载请求时,我的代码就挂接到该方法.

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

导航响应的类型为URLResponse,它无法提取响应的主体内容,这是一个简单的JSON.如下所示:

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'
}

在代码的本机端是否有从wkwebview迅速获取响应主体的方法?

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
}

相反,我使用了此回调并在结果上执行了一些javascript:

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

id"my-id"来自我在此服务后端构建的响应,以防万一Web视图将任何其他HTML包裹在响应周围.我的初衷是无需运行任何JavaScript即可执行此操作,但我想没有其他方法.无论如何,这个效果很好.

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.