Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >实现 iOS 无感知上拉加载更多

实现 iOS 无感知上拉加载更多

作者头像
网罗开发
发布于 2021-08-13 08:23:26
发布于 2021-08-13 08:23:26
2.5K00
代码可运行
举报
文章被收录于专栏:网罗开发网罗开发
运行总次数:0
代码可运行

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

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

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

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

如何实现

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

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 的代码少,先试试再说,于是代码撸起:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 文件查看:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// 设置尾部刷新控件,更新为无感知加载更多
let footer = MJRefreshAutoFooter()
footer.triggerAutomaticallyRefreshPercent = -1
tableView.mj_footer = footer

再来看看效果:

直接说感受:

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

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

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

MJRefresh代码的追根朔源

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

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

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

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

MJRefreshAutoFooter => MJRefreshFooter => MJRefreshComponent

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

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

  • MJRefreshComponent 是通过 KVO 去监听 scrollViewcontentOffset 变化,思路上我们对齐一致了。
  • 该类并没有实现其具体方法,而是将其交由其子类去实现,这一点通过看 MJRefreshComponent.h 的注释可以得到:
  • MJRefreshComponent 从本质上更像虚基类。

总结

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

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

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

iOS 关于列表上拉(平滑加载数据)自动加载数据的问题[1]

MJRefresh小技巧(上拉提前刷新)[2]

参考资料

[1]

iOS 关于列表上拉(平滑加载数据)自动加载数据的问题: https://www.jianshu.com/p/55c0f5b5670f

[2]

MJRefresh小技巧(上拉提前刷新): https://www.jianshu.com/p/227976796819

-End-

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-08-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 网罗开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
六天完成一个简单iOS App - 第四天
第四天任务: 今天主要任务完成精华模块的搭建。 精华页面的搭建 精华页面中全部界面的显示 日期的处理 热门评论的显示和处理 精华页面的搭建 精华页面分为全部、视频、声音、图片、段子五个界面,五个界面可
xx_Cc
2018/05/10
1.5K0
iOS开发之多表视图滑动切换示例(仿"头条"客户端)
  好长时间没为大家带来iOS开发干货的东西了,今天给大家分享一个头条新闻客户端各个类别进行切换的一个示例。在Demo中对所需的组件进行的简单封装,在封装的组件中使用的是纯代码的形式,如果想要在项目中进行使用,稍微进行修改即可。   废话少说,先介绍一下功能点,下图是整个Demo的功能点,最上面左边的TabBarButtonItem是用来减少条目的,比如下图有三个按钮,点击减号会减少一个条目。右边的为增加一个条目。点击相应的按钮是切换到对应的表视图上,下方红色的是滑动的指示器,同时支持手势滑动。运行具体效果
lizelu
2018/01/11
3.8K0
iOS开发之多表视图滑动切换示例(仿"头条"客户端)
竭尽全力的去解耦的一次实践,封装一个TableView和一些功能组合的控件
可以先看看这个Demo:https://github.com/ming1016/DecoupleDemo。从这个Demo里可以看到Controller和View还有Store的头文件里没有任何Delegate,Block回调,只有初始化和更新ViewModel的方法。所有这些控件,请求,ViewController和视图之间的联系都是通过ViewModel来进行的,而viewModel也不进行任何逻辑处理,只是简单的起到描述和默认值设置的作用。ViewController也被减轻的小得不能再小了,只需要初始化视图和Store即可。这也是我的一次尝试,看看如何利用KVO能够做到最大限度的解耦,和最大限度的减少代码和接口。
用户7451029
2020/06/16
6630
微信小程序实现上拉加载更多
微信小程序当页面滑到底部,如何上拉加载更多数据,我们需要用onReachBottom方法实现,当滑动到底部,页码+1请求服务器,并设置数据。
Petrochor
2022/06/07
2.6K0
iOS开发中使用UITableView提高用户体验
1.在使用了MJRefresh之后,当UITableView滑到底部的时候需要继续上拉(比之前的上拉费力)才能进行刷新。
用户1451823
2018/09/13
1K0
iOS开发中使用UITableView提高用户体验
iOS UITableView 滑动到底部加载更多数据
很多APP都是滑动到底部时点击加载更多才会加载数据,这样用户体验就会有间断感,所以我们想用户看到最后时自动加载数据 怎么做呢
码客说
2019/10/22
2.4K0
RxSwift + MJRefresh 打造自动处理刷新控件状态
本文是基于 iOS - RxSwift 项目实战记录 所述,如果你还未阅读过,建议你最好还先阅读一遍,并下载Demo熟悉一下 : ) LXFBiliBili 前言 MVVM的模式中,多出了View
LinXunFeng
2018/06/29
2K0
Android——RecyclerView自定义OnScrollListener实现下拉刷新监听,上拉加载更多功能
针对RecyclerView有很多开源的框架可以直接拿来用,比较有代表性的是BaseRecyclerViewAdapterHelper,功能很强大,具备上拉监听的功能。使用开源的东西固然省时省力,但是前期自定义的Adapter使用较多,不想再更改了,且总使用开源的东西慢慢人都变傻了,这个功能不算复杂,就自己查找相关资料参照实现了。
Winter_world
2020/09/25
3.8K0
MJRefresh源码剖析与学习
建议查看原文:https://www.jianshu.com/p/23c876f8ae39(不定时更新)
Dwyane
2018/09/30
1.6K0
MJRefresh源码剖析与学习
【Flutter】ListView 列表高级功能 ( ScrollController 上拉加载更多 )
在 FLutter 中 , 所有的列表都支持设置一个 ScrollController 类型的参数 ,
韩曙亮
2023/03/29
2.2K0
【Flutter】ListView 列表高级功能 ( ScrollController 上拉加载更多 )
iOS开源组件分类总结
下拉刷新 ZJRefreshControl ZJRefreshControl 下拉刷新 加载更多 Swift 调用方式 //只有下拉刷新 refreshControl = ZJRefreshControl(scrollView: appTableView, refreshBlock: { self.dropViewDidBeginRefreshing() }) //下拉刷新和上拉加载更多 refreshControl = ZJRefreshControl(scrollView: msgT
码客说
2019/10/22
9710
QQ空间掉帧率优化实战
空间新业务需求日益增多,在业务开发阶段的疏忽,或者是受到其他业务的影响(比如一些非空间的业务网络回包或者逻辑在主线程进行),导致空间的某些页面掉帧率上升。
WeTest质量开放平台团队
2018/10/29
1.4K0
高效学习iOS —— Stroke和路径动画
先添加需要的代码,这里需要将storyboard的ViewController换成
CC老师
2022/01/14
2K0
高效学习iOS —— Stroke和路径动画
UITableView性能优化-中级篇
老实说,UITableView性能优化 这个话题,最经常遇到的还是在面试中,常见的回答例如:
小蠢驴打代码
2018/12/27
1.7K0
Flutter ScrollView上拉加载更多关于学习
2018.05.07 更新 上拉加载可以不用Notification,直接用ScrollController,代码如下:
吴老师
2018/09/05
2K0
QQ空间掉帧率优化实战
本文主要介绍了如何通过分析iOS App在运行过程中产生的CPU、内存、网络等方面的数据,从而定位App的卡顿、掉帧原因。同时,介绍了一些优化手段,帮助开发者在App开发过程中,提高产品的性能。
WeTest质量开放平台团队
2017/12/08
1.9K0
QQ空间掉帧率优化实战
iOS开发-1.UITableView你会用吗?
前一段时间,公司招聘了一个新员工,界面做出来了,但是很卡,我看完他写的代码,发现没有对UITableViewCell进行循环使用,而且在UITableView代理方法中,创建了很多并没有什么用的对象,一些调用频繁的方法也没有很好地处理。
孙寅
2020/06/03
8940
vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多
  用vue来实现一个瀑布流效果,加载网络图片,同时有下拉刷新和上拉加载更多功能效果。然后针对这几个效果的实现,捋下思路:
tandaxia
2020/01/16
3.6K1
vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多
自定义RecyclerView下拉刷新上拉加载更多
自定义ListView下拉刷新上拉加载更多 自定义RecyclerView下拉刷新上拉加载更多
cMusketeer
2022/10/27
1.1K0
移动端下拉刷新、上拉加载更多 Jquery插件 dropload
a javascript implementation of pull to refresh and up to loadmore 移动端下拉刷新、上拉加载更多插件
王念博客
2019/07/25
6.2K0
推荐阅读
相关推荐
六天完成一个简单iOS App - 第四天
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验