最近为公司项目中添加自动加载更多功能,因而将公司里下拉刷新和加载更多功能单独抽出来,放在UITableView的category中,能够作到无侵入添加这些功能,使得不少老代码只须要几句代码,便可实现这些功能。具体代码及使用方法:UITableView+PullData,其实实现逻辑很简单,基本看完代码就能彻底理解,可是在实现的时候,遇到了一些问题,下面内容主要讲讲我是如何去解决这些问题的。git
首先,公司以前代码就实现了下拉刷新和上拉加载更多功能,是经过继承基类UITableView,在子类中添加属性enablePullDataRefresh、enablePullDataLoadMore、pullDataDelegate、pullDataTableViewIsRefreshing、pullDataTableViewIsLoadingMore及代理方法去实现,具体的实现和个人代码基本一致,用子类的方式不是很优雅,每一个想实现这个功能都须要用子类建立实例。若是用category的方式,就能够作到彻底不用改变原有代码,只须要设置tableview的属性值,就能够实现功能,这里用的老思路,也没有遇到大问题,只有一些小问题,简单优化了下。github
主要的坑在自动加载更多上,自动加载更多就是在滑动UI TableView的时候,当快到底部时,提早本身去发起加载后面数据的请求并添加到数据源上,让用户没有感知的状况加载了新数据。post
能够想到要提早加载数据,何时发起请求呢?经过什么方式去获取条件是否知足呢?预加载与智能预加载(iOS)这篇博客讲了一种Threshold方式,能够经过Threshold值来肯定触发条件,由scrollViewDidScroll去获取条件。因而很快就实现了自动加载功能,可是会有一个问题,每一个想实现自动加载更多功能,都须要实现UITableView的scrollViewDidScroll代理方法,连代理方法里的代码都几乎同样,这样的实现方式不是太好看。优化
既然把触发自动加载更多的条件及监测方式放在UITableView的代理上,不是很好,换个方式实现吧。scrollViewDidScroll代理方法都会伴随着contentOffset发生变化,咱们能够经过监听contentOffset的值来判断条件是否成立,当条件知足的时候让tableView加载更多数据,天然会想到用KVO观察contentOffset的值发生变化,而后一系列判断是否知足条件。为了无侵入的设置自动加载更多,让tableview本身观察本身的contentOffset,当loadMoreStyle = TableViewLoadMoreStyleAuto时添加KVO观察,loadMoreStyle = TableViewLoadMoreStyleDefault时移除KVO观察。那么问题就来了,若是子类tableView本身也使用KVO会致使父类里的不执行,好吧,我想到若是要继承UITableView,就须要在+(void)load里去hook这个- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context方法,我用宏定义去帮助如何去hook,只须要在继承的时候写上方法+ (void)load {AutoLoadMoreMacro};,问题好像是解决了,可是问题又来了,大神说KVO不能够屡次移除观察者等问题,若是我屡次设置loadMoreStyle = TableViewLoadMoreStyleDefault就会出现问题,不得已又放弃KVO这种方式。线程
既然知道contentOffset值会变,KVO观察不能够,索性直接hook setContentOffset方法,在里面去判断是否知足自动加载更多条件,判断条件就是经过contentOffset.y和contentSize.height值作比较,当差值小到一个值,去执行加载更多,这样基本实现了自动加载,终于能够舒口气了,可是又发现一个问题,每次加载的时候都会触发两次,检查各个条件都是正确的,setContentOffset也是主线程里执行,怀疑可能setContentOffset里contentOffset.y和contentSize.height值作比较这种方式会有抖动,因而又要换个方式,直接拿数据源比较吧,tableView能够获取numberOfRowInSection,还有indexPathsForVisibleRows属性,能够经过比较可见的row和总row值比较来肯定触发条件,可是这么作,只能让tableview只有一个section。代理
以上就是我作自动加载更多遇到的问题,但愿你们能够多多交流,发现一些不足,以及给予一些更好的实现方式。继承