Search code examples
iosobjective-cswiftwkwebview

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?


Solution

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