本文所用方法会使用到苹果私有API,上架APP Store请谨慎使用。
需求
获取UIWebView
的前进后退的浏览记录,举个例子,比如从A->B->C->B,此时B上一页是A,下一页是C,需要获取A、C的URL信息。
WKWebView暴露了这个属性,
WKBackForwardList *backForwardList
。可以很容易的取到,无奈项目还是使用的UIWebView
,于是有了后面的探索。
首先在UIWebView
提供的API里找,相关的API只有canGoBack
和canGoForward
,命名很直观,是否可以后退和前进,这条路走不通。
想到是否可以通过JS的Window.history获取到,查了下API,唯一一个有点像的length
属性,智能取到浏览记录中的所有URL的数量,不区分前后,比如在上面提到的例子中,在B页面取到的length
是3,而且不能取出具体的URL。
无奈只有上源码了,我下载的是“WebKit-7604.1.38.0.7”和“WebCore-7604.1.38.0.7”。
Window.History.length实现本质
在WebCore里面找到了JS方法Window.History.length
实现的本质,上代码:
1 | // WebCore History.cpp |
1 | // WebCore BackForwardController.cpp |
在WebCore
里面backListCount()
、forwardListCount()
定义是虚函数,具体实现在WebKit
可以找到。
1 | // WebKit BackForwardList.mm |
还有一个方法我们需要关注一下,后面会用到。
1 | // WebKit BackForwardList.mm |
获取History
在WebView
的中,我们可以找到WebBackForwardList
的定义。
1 | /*! |
WebBackForwardList
是对BackForwardList
的一层封装,阅读一下它的.h文件,不难找到获取浏览记录的方法。
1 | /*! |
上面的方法可以获取到一个WebHistoryItem
数组,WebHistoryItem
保存了浏览记录的详细信息。
获取WebBackForwardList
UIWebView
没有暴露获取WebView
或者WebBackForwardList
的方法,但是我们可以用KVO曲线救国,于是我们需要找到WebView
的私有变量名。用runtime可以做到,为了简化这个过程,我写了一个工具类来辅助搜索,具体可以看这篇文章-runtime实现私有变量搜索。简单来说就是用runtime获取类成员变量列表,然后用BFS来搜索我们要找的类。
1 | // 以UIWebView为根节点,BFS搜索WebView |
有了上面的结论,我们就可以用KVC来获取到浏览记录了。
1 | - (void)printWebViewHistory:(UIWebView *)aWebView { |