问题
I want to get my UIWebView's current location when browsing an SPA (single-page-application) website.
(Yes, I am intentionally working with UIWebView instead of WKWebView.)
I know that there are multiple approaches to getting the current URL, such as:
webView.request?.url?.absoluteString
webView.request?.mainDocumentURL?.absoluteString
webView.stringByEvaluatingJavaScript(from: "window.location")
However, for an SPA website, for each of the approaches above, I am getting the initial url, even when I navigate to another page on that SPA website.
What can I do?
回答1:
Step 1: Creating a custom URLProtocol to catch data requests
class CustomURLProtocol: URLProtocol, URLSessionDataDelegate, URLSessionTaskDelegate {
    // If this returns false, the first request will basically stops at where it begins.
    override class func canInit(with request: URLRequest) -> Bool {
        return true
    }
    override class func canonicalRequest(for request: URLRequest) -> URLRequest {
        return request
    }
    override func startLoading() {
        print(self.request.url) // URL of Data requests made by UIWebView before loading.  
        URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil).dataTask(with: self.request).resume()
    }
    override func stopLoading() {
    }
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
        // Data request responses received.  
        self.client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .allowed)
        completionHandler(.allow)
    }
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
        // Data request data received.
        self.client?.urlProtocol(self, didLoad: data)
        self.urlSession(session, task: dataTask, didCompleteWithError: nil)
    }
    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        if let error = error {
            self.client?.urlProtocol(self, didFailWithError: error)
            return
        }
        print(self.request.url) // URL of Data requests completed.
        self.client?.urlProtocolDidFinishLoading(self)
    }
}
Step 2: Registering your custom URLProtocol
Register your custom URLProtocol before loading your SPA in UIWebview.
URLProtocol.registerClass(CustomURLProtocol.self)
Hope this helps! Sorry for the delay, was caught up at work.
来源:https://stackoverflow.com/questions/53864836/uiwebview-get-current-url-of-spa-single-page-application-website