Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to clear the WKBackForwardList of a WKWebView?

It appears that the backForwardList of a WKWebView is readonly, but I've seen people so some pretty magical things to get around this. I need to figure out some way of clearing the history of a WKWebView. Any ideas how I might so this? So far I've tries a few tricks that have failed:

  • using keyValue:forKey didn't work.
  • using a C pointer -> didnt work.

I've seen people talk about synthesizing the property and extending the class but I don't really know how that works and couldn't figure it out. Any other ideas?

like image 315
Chet Avatar asked Sep 07 '17 01:09

Chet


2 Answers

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。

like image 86
xu tong Avatar answered Sep 18 '22 11:09

xu tong


This code compiles, but I have not tested it...

First I subclass WKWebView to override backForwardList with my own subclass of WKBackForwardList.

Then, in my WKBackForwardList subclass, I can either override backItem & forwardItem to make them return nil, instead of having them look into their respective list (which is most probably the default implementation).

Or I can override backList & forwardList in the same way I did in WKWebView with backForwardList. I do this to add a setter, which will allow me remove items from the lists.

import Foundation
import WebKit

class WebViewHistory: WKBackForwardList {

    /* Solution 1: return nil, discarding what is in backList & forwardList */

    override var backItem: WKBackForwardListItem? {
        return nil
    }

    override var forwardItem: WKBackForwardListItem? {
        return nil
    }

    /* Solution 2: override backList and forwardList to add a setter */

    var myBackList = [WKBackForwardListItem]()

    override var backList: [WKBackForwardListItem] {
        get {
            return myBackList
        }
        set(list) {
            myBackList = list
        }
    }

    func clearBackList() {
        backList.removeAll()
    }
}

class WebView: WKWebView {

    var history: WebViewHistory

    override var backForwardList: WebViewHistory {
        return history
    }

    init(frame: CGRect, configuration: WKWebViewConfiguration, history: WebViewHistory) {
        self.history = history
        super.init(frame: frame, configuration: configuration)
    }

    /* Not sure about the best way to handle this part, it was just required for the code to compile... */

    required init?(coder: NSCoder) {

        if let history = coder.decodeObject(forKey: "history") as? WebViewHistory {
            self.history = history
        }
        else {
            history = WebViewHistory()
        }

        super.init(coder: coder)
    }

    override func encode(with aCoder: NSCoder) {
        super.encode(with: aCoder)
        aCoder.encode(history, forKey: "history")
    }
}
like image 37
nyg Avatar answered Sep 18 '22 11:09

nyg