How to clear the WKBackForwardList of a WKWebView?

Worded on iOS8 ~ iOS11.

Objective-C

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[wek.backForwardList performSelector:NSSelectorFromString(@"_removeAllItems")];
#pragma clang diagnostic pop

Swift 4

webView.backForwardList.perform(Selector(("_removeAllItems")))

!!!!NOTE!!!! THIS METHOD IS DECLARED IN WebKit Open Resource, not a public method。


Because Apple keeps the interface for WKBackForwardList pretty tightly locked down and is notoriously strict with developers who go outside of the published public interfaces, you have two options:

  1. The easiest way (and surely what Apple intends) is to create a new WKWebView and replace your current one with it. This isn't that hard of a solution to implement since there are a pretty finite number of configurations you could have to copy over from your old instance to your new one. You could even create a wrapper view that did this for you, so that you only ever had to call clearHistory() and the wrapper view would do the underlying swap for you.

  2. If, for some reason, you can't replace the instance of WKWebView, you can take advantage of the 1D nature of history to clear the history down to two items. You cannot clear it farther than that, I'm afraid. To clear the URL down to two URLs, let's say they're stored in the values urlA and urlB, you would do:

// At initialization, ensure that urlA is the first item in the history
let webview = WKWebView()
// ... whatever other init you need
webview.load(URLRequest(url: urlA))

and then to "clear" the history:

func clearHistory() {
    // First we make sure the webview is on the earliest item in the history
    if webview.canGoBack {
        webview.go(to: webview.backForwardList.backList.first)
    }
    // Then we navigate to our urlB so that we destroy the old "forward" stack
    webview.load(URLRequest(url: urlB))
}