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

目录
  • 什么是无感知上拉加载更多
  • 如何实现无感知上拉加载更多
  • 网上的思路(一)
  • 网上的思路(二)
  • MJRefresh代码的追根朔源
  • 总结

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

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

如果要体验话,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上拉加载更多内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

参考文章

时间: 2021-07-10

ios基于MJRefresh实现上拉刷新和下拉加载动画效果

本文介绍了ios基于MJRefresh实现上拉刷新和下拉加载动画效果,分享给大家,具体如下: 目录 1. 头部刷新动画 2.尾部刷新动画 头部刷新动画 #import <MJRefresh/MJRefresh.h> @interface HZNormalHeader : MJRefreshGifHeader @end #import "HZNormalHeader.h" @implementation HZNormalHeader #pragma mark - 重写父类的方

iOS实现MJRefresh下拉刷新(上拉加载)使用详解

下拉刷新控件目前比较火的有好几种,本人用过MJRefresh 和 SVPullToRefresh,相对而言,前者比后者可定制化.拓展新都更高一点. 因此本文着重讲一下MJRefresh的简单用法. 导入项目: cocoapods导入:pod 'MJRefresh' 手动导入: 将MJRefresh文件夹中的所有文件拽入项目中 导入主头文件:#import "MJRefresh.h" 使用介绍: 广泛性分为6种使用场景,分别对应:默认.动画图片.隐藏时间.隐藏时间和状态.自定义文字说明.

iOS开发之UITableView与UISearchController实现搜索及上拉加载,下拉刷新实例代码

废话不多说了,直接给大家贴代码了. 具体代码如下所示: #import "ViewController.h" #import "TuanGouModel.h" #import "TuanGouTableViewCell.h" #define kDeviceWidth [UIScreen mainScreen].bounds.size.width #define kDeviceHeight [UIScreen mainScreen].bounds.

举例讲解iOS中延迟加载和上拉刷新/下拉加载的实现

lazy懒加载(延迟加载)UITableView 举个例子,当我们在用网易新闻App时,看着那么多的新闻,并不是所有的都是我们感兴趣的,有的时候我们只是很快的滑过,想要快速的略过不喜欢的内容,但是只要滑动经过了,图片就开始加载了,这样用户体验就不太好,而且浪费内存.              这个时候,我们就可以利用lazy加载技术,当界面滑动或者滑动减速的时候,都不进行图片加载,只有当用户不再滑动并且减速效果停止的时候,才进行加载.               刚开始我异步加载图片利用SDWe

jQuery模拟原生态App上拉刷新下拉加载更多页面及原理

很多App中,新闻或者展示类都存在下拉刷新和上拉加载的效果,网上提供了实现这种效果的第三方类(详情请见MJRefresh和EGOTableViewPullRefresh),用起来很方便,但是闲暇之余,我们可以思考下,这种效果实现的原理是什么,我以前说过,只要是动画都是骗人的,只要不是硬件问题大部分效果都能在系统UI的基础上做出来. 下面通过jQuery手机端上拉下拉刷新页面代码,很像QQ空间客户端或者微信下拉刷新页面特效代码. 请看下面效果图: 在线预览    源码下载 html代码: <div

MUI 上拉刷新/下拉加载功能实例代码

新闻信息列表必备的功能,支持Table,Ul等列表. 以下是DIV版本,在安卓端或者ios端必须使用双webview模式,传送门:http://dev.dcloud.net.cn/mui/pulldown/ <!--下拉刷新容器--> <div id="pullrefresh" class="mui-content mui-scroll-wrapper"> <div class="mui-scroll"> &l

Android手把手教大家制作APP首页(下拉刷新、自动加载)

一.概述 作为一名三年Android开发经验的程序员,今天和大家一起实战一款APP的首页功能,这个首页在我们平时接触中还是很常见的,虽然页面简单,但是里面涉及的功能点还是挺多的.代码如有不足的还望各路同仁指点一二. 页面中使用的开发库: 整个首页架构使用的是LRecyclerView,包含下拉刷新和自动加载功能 compile 'com.github.jdsjlzx:LRecyclerView:1.3.3' 无限循环轮播图使用的是convenientbanner,效果还是很顺畅的,还可以根据自己

iOS中的UITableView的重用机制与加载优化详解

UITableView可以说是UIKit中最重要的一个组件,用来展示数据列表,还可以灵活使用进行页面的布局.UITableView的使用遵循MVC模式,数据模型(NSObject).视图(UIView)和控制器(UITableViewController)分离.UITableView继承自UIScrollView,可上下滑动,可以作为跟视图也可以作为子视图组件. reuseIdentifier顾名思义是一个复用标识符,是一个自定义的独一无二的字符串,用来唯一地标记某种重复样式的可复用UITabl

android使用PullToRefresh框架实现ListView下拉刷新上拉加载更多

本文实例为大家分享了Android实现ListView下拉刷新上拉加载更多的具体代码,供大家参考,具体内容如下 其实谷歌官方目前已经推出ListView下拉刷新框架SwipeRefreshLayout,想了解的朋友可以点击 android使用SwipeRefreshLayout实现ListView下拉刷新上拉加载了解一下: 大家不难发现当你使用SwipeRefreshLayout下拉的时候布局文件不会跟着手势往下滑,而且想要更改这个缺陷好像非常不容易. 虽然SwipeRefreshLayout非

Android使用recyclerview打造真正的下拉刷新上拉加载效果

前言 前段时间需要用到recyclerview,就想找个封装好的下拉刷新,上拉加载的库,结果愣是没找到,便自己写了一个. 注意:我说的是"上拉加载",不是滑到底部自动加载. 虽然现在自动加载是主流和趋势,但也不排除有时候就需要用到上拉加载啊,毕竟林子大了,什么样的产品经理都有对吧. 代码写好后,准备发布到bintray的时候,向同事征求这个项目的名字,同事说:"就叫DZTRecyclerview!" 不解,同事解释:"叼炸天Recyclerview!&qu

android RecyclerView侧滑菜单,滑动删除,长按拖拽,下拉刷新上拉加载

本文介绍的库中的侧滑效果借鉴自SwipeMenu,并对SipwMenu的源码做了修改与Bug修复,然后才开发出的SwipeRecyclerView. 需要说明的是,本库没有对RecyclerView做大的修改,只是ItemView的封装.看起来是对RecyclerView的修改,其实仅仅是为RecyclerView添加了使用的方法API而已. 本库已经更新了三个版本了,会一直维护下去,根据小伙伴的要求,以后也会添加一些其它功能. SwipeRecyclerView将完美解决这些问题: 以下功能全

android中SwipeRefresh实现各种上拉,下拉刷新示例

SwipeRefresh 基于原生的SwipeRefreshLayout 做了封装处理 此项目中包括种: 1.原生SwipeRefreshLayout(上拉可通过滚动监听实现) 2.自定义支持上拉刷新的组件 3.自定义支持ViewPage的刷新组件VPSwipeRefreshLayout 4.RecyclerView+SwpieRefreshLayout实现下拉刷新效果同时实现上拉功能 主界面 1.原生SwipeRefreshLayout(上拉可通过滚动监听实现) 除了OnRefreshList

React Native 自定义下拉刷新上拉加载的列表的示例

在移动端开发中列表页是非常常见的页面,在React Native中我们一般使用FlatList或SectionList组件实现这些列表视图.通常列表页都会有大量的数据需要加载显示,这时候就用到了分页加载,因此对于列表组件来说,实现下拉刷新和上拉加载在很多情况下是必不可少的. 本篇文章基于FlatList封装一个支持下拉刷新和上拉加载的RefreshListView,对原始的FlatList进行封装之后,再调用上拉和下拉刷新就十分方便了. 下拉刷新的实现十分简单,这里我们沿用FlatList本身的