iOS实现无感知上拉加载更多功能的思路与方法

 更新时间:2021年7月12日 15:00  点击:1896

什么是无感知上拉加载更多

什么是无感知,这个这样理解:在网络情况正常的情况下,用户对列表进行连续的上拉时,该列表可以无卡顿不停再见新的数据。

如果要体验话,Web端很多已经做到了,比如掘金的首页,还有比如i掘金iOS的App,列表都是无感知的。

说来惭愧,写了这久的代码,还真的没有认真思考这个功能怎么实现。

如何实现无感知上拉加载更多

我在看见这位网友留言的时候,就开始思考了。

在我看来,有下面几个着手点:

  • 列表滑动时候的是如何知道具体滑动的位置以触发接口请求,添加更多数据?
  • 从UIScrollView的代理回调中去找和scrollView的位置(contentOffset)大小(contentSize)关系密切的回调。
  • 网络上有没有比较成熟的思路?

顺着这条线,我先跑去看了UIScrollViewDelegate的源码:

public protocol UIScrollViewDelegate : NSObjectProtocol {

    
    @available(iOS 2.0, *)
    optional func scrollViewDidScroll(_ scrollView: UIScrollView) // any offset changes

    @available(iOS 3.2, *)
    optional func scrollViewDidZoom(_ scrollView: UIScrollView) // any zoom scale changes

    .
    .
    .
    .
    .
    .
    /// 代码很多,这里就不放上来,给大家压力了。
}

直接上结论吧:看了一圈,反正没有和contentSize或者位置相关的回调代理。scrollViewDidScroll这个回调里面虽然可以知道scrollView,但是对于我们需要的信息还不够具体。

思考:既然UIScrollViewDelegate的代理没有现成的代理回调,自己使用KVO去监听试试?

网上的思路(一)

就在我思考的同时,我也在网络上需求实现这个功能的答案,让后看到这样一个思路:

实现方法很简单,需要用到tableView的一个代理方法,就可轻松实现。- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath就是这个方法,自定义显示cell。这个方法不太常用。但是这个方法可在每个cell将要第一次出现的时候触发。然后我们可设置当前页面第几个cell将要出现时,触发请求加载更多数据。

我看了之后,心想着,多写一个TableView的代理,总比写KVO的代码少,先试试再说,于是代码撸起:

extension SwiftCoinRankListController: UITableViewDelegate {
    
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        let row = indexPath.row
        let distance = dataSource.count - 25
        print("row: \(row), distance:\(distance)  ")
        if row == distance {
            loadMore()
        }
    }
}

本代码可以在开源项目中的SwiftCoinRankListController.swift文件查看具体的逻辑,其主要就是通过cell显示的个数去提前请求加载数据,然后我们看看效果:

Gif可能看起来还好,我说我调试的感受:虽然做到了上拉无感知,但是当手滑的速度比较快的时候,到底了新的数据没有回来,就会在底部等一段时间。

虽然功能达到了,但是感受却不理想,果然还是监听的细腻程度不够。

网上的思路(二)

然后在继续的搜索中,我看到了另外一个方案:

很多时候我们上拉刷新需要提前加载新数据,这时候利用MJRefreshAutoFooter的属性triggerAutomaticallyRefreshPercent就可以实现,该属性triggerAutomaticallyRefreshPercent默认值为1,然后改成0的话划到底部就会自动刷新,改成-1的话,在快划到底部44px的时候就会自动刷新。

MJRefresh?使用MJRefreshAutoFooter,这个简单,我直接把基类的footer给替换掉就可以了,本代码可以在开源项目中的BaseTableViewController.swift文件查看:

/// 设置尾部刷新控件,更新为无感知加载更多
let footer = MJRefreshAutoFooter()
footer.triggerAutomaticallyRefreshPercent = -1
tableView.mj_footer = footer

再来看看效果:

直接说感受:

代码改动性少,编写简单,达到预期效果,爽歪歪。比的方案一更丝滑,体验好。

到此,功能就实现,难道就完了?

当然,不会,我们去看看源码吧。

MJRefresh代码的追根朔源

首先我们看看MJRefreshAutoFooter.h文件:

这里有个专门的属性triggerAutomaticallyRefreshPercent去做自动刷新,那么我们去MJRefreshAutoFooter.m中去看看吧:

注意看看喔,这个.m文件有一个- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change方法,并且还调用了super,从这个方法名中我们可以明显的得到当scrollView的contentOffset变化的时候进行回调的监听。,我们顺藤摸瓜,看看super是什么,会不会有新的发现:

稍微跟着一下源代码,MJRefreshAutoFooter的继承关系如下:

MJRefreshAutoFooter => MJRefreshFooter => MJRefreshComponent

所以这个super的调用我们就去MJRefreshComponent.m里面去看看吧:

通过上面的截图我们可以得到下面的一些信息与结论:

  • MJRefreshComponent是通过KVO去监听scrollView的contentOffset变化,思路上比较一致。
  • 该类并没有实现其具体方法,而是将其交由其子类去实现,这一点通过看MJRefreshComponent.h的注释可以得到:

  • MJRefreshComponent从本质上更像虚基类。

总结

如果不是网友提出这个问题,我可能都不会太仔细的去研究这个功能,也许继续普普通通的使用一般的上拉加载更多就够了。

这次的实践,其实是从思路到寻找方法,最后再到源码阅读的。

思路也许不困难,但是真正一点点实现并完善功能,每一步都并不容易,这次我也仅仅是继续使用了MJRefresh这个轮子。

到此这篇关于iOS实现无感知上拉加载更多功能的思路与方法的文章就介绍到这了,更多相关iOS上拉加载更多内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

参考文章

  • iOS 关于列表上拉(平滑加载数据)自动加载数据的问题
  • MJRefresh小技巧(上拉提前刷新)
[!--infotagslink--]

相关文章

  • MySQL性能监控软件Nagios的安装及配置教程

    这篇文章主要介绍了MySQL性能监控软件Nagios的安装及配置教程,这里以CentOS操作系统为环境进行演示,需要的朋友可以参考下...2015-12-14
  • iOS APP h5快捷程序 .mobileconfig的生成

    1.从APP Store 下载Apple Configurator 2从一个管理点管理所有iOS设备应用程序,文档和配置文件。想要确保您的所有家庭成员在其每台iOS设备上都有类似的应用和文档,管理日益增...2021-12-23
  • iOS设置UIButton文字显示位置和字体大小、颜色的方法

    这篇文章给大家分享了iOS如何设置UIButton的文字显示位置和字体的大小、颜色,文中给出了示例代码,相信对大家的学习和理解很有帮助,有需要的朋友们下面来一起看看吧。...2020-06-30
  • iOS如何将图片裁剪成圆形

    这篇文章主要为大家详细介绍了iOS如何将图片裁剪成圆形,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-30
  • 用js的document.write输出的广告无阻塞加载的方法

    一、广告代码分析很多第三方的广告系统都是使用document.write来加载广告,如下面的一个javascript的广告链接。复制代码 代码如下:<script type="text/javascript" src="http://gg.5173.com/adpolestar/5173/;ap=2EBE5...2014-06-07
  • jQuery页面加载初始化常用的三种方法

    当页面打开时我们需要执行一些操作,这个时候如果我们选择使用jquery的话,需要重写他的3中方法,自我感觉没什么区 别,看个人喜好了,第二种感觉比较简单明了: 第一种: 复制代码 代码如下: <script type="text/javas...2014-06-07
  • iOS给border设置渐变色的方法实例

    这篇文章主要给大家介绍了关于iOS给border设置渐变色的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-09
  • 解决IDEA插件市场Plugins无法加载的问题

    这篇文章主要介绍了解决IDEA插件市场Plugins无法加载的问题,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-10-21
  • Android WebView加载html5页面实例教程

    如果我们要在Android应用APP中加载html5页面,我们可以使用WebView,本文我们分享两个WebView加载html5页面实例应用。 实例一:WebView加载html5实现炫酷引导页面大多...2016-09-20
  • iOS新版微信底部返回横条问题的解决

    这篇文章主要介绍了iOS新版微信底部返回横条问题的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-30
  • Angular性能优化之第三方组件和懒加载技术

    这篇文章主要介绍了Angular性能优化之第三方组件和懒加载技术,对性能优化感兴趣的同学,可以参考下...2021-05-11
  • 几种延迟加载JS代码的方法加快网页的访问速度

    本文介绍了如何延迟javascript代码的加载,加快网页的访问速度。 当一个网站有很多js代码要加载,js代码放置的位置在一定程度上将会影像网页的加载速度,为了让我们的网页加载速度更快,本文总结了一下几个注意点...2013-10-13
  • ThinkPHP+jquery实现“加载更多”功能代码

    本篇文章主要介绍了ThinkPHP+jquery实现“加载更多”功能代码,以实例代码讲诉了加载更多的代码实现,非常具有实用价值,需要的朋友可以参考下 ...2017-03-13
  • 解决vue动态路由异步加载import组件,加载不到module的问题

    这篇文章主要介绍了解决vue动态路由异步加载import组件,加载不到module的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-27
  • AngularJS 实现按需异步加载实例代码

    AngularJS 通过路由支持多视图应用, 可以根据路由动态加载所需的视图, 在 AngularJS 的文档中有详细的介绍, 网上也有不少教程, 就不用介绍了!随着视图的不断增加,js文件会越来越多,而 AngularJS 默认需要把全部的js都一次性...2015-10-21
  • vue+axios全局添加请求头和参数操作

    这篇文章主要介绍了vue+axios全局添加请求头和参数操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-24
  • iOS蓝牙设备名称缓存问题的解决方法

    这篇文章主要给大家介绍了关于iOS蓝牙设备名称缓存问题的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-12-08
  • vue3如何按需加载第三方组件库详解

    距离 Vue 3.0 正式版发布已经有一段时间了,关于vue3组件库相关的问题还是挺多人感兴趣的,这篇文章主要给大家介绍了关于vue3如何按需加载第三方组件库的相关资料,需要的朋友可以参考下...2021-06-02
  • iOS新版微信底部工具栏遮挡问题完美解决

    这篇文章主要介绍了iOS新版微信底部工具栏遮挡问题完美解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-30
  • 用C++面向对象的方式动态加载so的方法

    下面小编就为大家带来一篇用C++面向对象的方式动态加载so的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-04-25