如何清除WKWebView的WKBackForwardList?

时间:2017-09-07 01:51:50

标签: ios objective-c swift wkwebview

看起来WKWebView的backForwardList是只读的,但我看到人们有一些非常神奇的东西来解决这个问题。我需要找出一些清除WKWebView历史的方法。任何想法我怎么可能这样?到目前为止,我尝试了一些失败的技巧:

  • 使用keyValue:forKey不起作用。
  • 使用C指针->无效。

我见过人们谈论合成属性和扩展课程,但我真的不知道它是如何工作的,也无法弄明白。还有其他想法吗?

4 个答案:

答案 0 :(得分:4)

此代码编译,但我没有测试过它......

首先,我将WKWebView子类化为使用我自己的backForwardList子类重写WKBackForwardList

然后,在我的WKBackForwardList子类中,我可以覆盖backItem& forwardItem使它们返回nil,而不是让它们查看各自的列表(这很可能是默认实现)。

或者我可以覆盖backList& forwardListWKWebView中使用backForwardList的方式相同。我这样做是为了添加一个setter,这将允许我从列表中删除项目。

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

答案 1 :(得分:2)

关注iOS8~iOS11。

目标-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")))

!!!!注!!!!这种方法在WebKit Open Resource中声明,而不是公共方法。

答案 2 :(得分:2)

由于Apple紧密锁定WKBackForwardList的界面,并且对published public interfaces以外的开发人员严格要求严格,因此您有两种选择:

  1. 最简单的方法(当然也是Apple的意图)是创建一个新的WKWebView并用它替换当前的clearHistory()。实施此解决方案并不难,因为您可能必须从旧实例复制到新实例的配置数量非常有限。您甚至可以创建一个为您执行此操作的包装器视图,这样您只需要调用WKWebView,包装器视图就可以为您进行基础交换。

  2. 如果由于某种原因而无法替换// 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)) 的实例,则可以利用历史记录的一维性质来清除历史记录,最多可以减少两个项目 >。恐怕您无法清除得更远。要将URL清除为两个URL,假设它们存储在值urlA和urlB中,您可以这样做:

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

然后“清除”历史记录:

+{}

答案 3 :(得分:1)

阅读文档可以获取WKWebView的WKBackForwardList。 之后,您可以在WKBackForwardList的backList中找到第一项,然后使用: func go(to: WKBackForwardListItem) -> WKNavigation? 这样您就可以清除历史记录直到第一个URL。