阅读源码之路终于开启了, 小白一枚, 大神们要多多照顾啊, 有什么建议可以评论或私信, 在此多谢了!!!!
概要
文章目录
- 前言
- API说明
- 原理解析
- 总结
1.前言
作为一个刷新框架, SVPullToRefresh以其简洁, 通俗易懂为大家所推崇. 对于刚开始读源码的我来说, 再合适不过了, 而且最近正在做一个刷新demo, 用到, 顺便整理一下, 学习学习.
SV是个熟悉的前缀, 就算没听过SVPullToRefresh, 也听过SVProgressHUD吧. 除了这些, 作者Sam还有其他优秀的开源代码, 大家感兴趣可以看看.
2.API说明
2.1 下拉刷新
下拉刷新ScrollView
下拉刷新View
👇是我自己测试的, 把所有属性玩了一遍, 亲测好用, O(∩_∩)O哈哈~
|
|
2.2 上拉刷新
上拉刷新ScrollView
上拉刷新View
附上测试效果:
|
|
3.原理解析
3.1 下拉刷新
以上是下拉刷新的主要流程图, 接下来我们就来扣扣细节;
3.1.1 -(void)triggerPullToRefresh
触发了一次刷新:
以下是方法的内部实现;
看了一眼, 当时就懵了; 怎么就这点儿代码, 完全看不出来啊, 别着急, 接着一个个点进去看. 发现state属性的setter方法里面做了处理;
接下来拆分一下:
执行完这步代码, 执行一次-(void)setState:
, 之后break跳出;
这步pullToRefreshView
执行-(void)startAnimating
, 方法内部实现如下:
可以看出之后又执行了一次-(void)setState:
, 这时previousState == SVPullToRefreshStateTriggered
条件满足, 执行infiniteScrollingHandler(), 也就执行了block里面刷新数据的方法;
3.1.2 利用runtime+KVO添加成员变量
代码如下:
关于KVO:
从代码中可以看出willChangeValueForKey :
和didChangeValueForKey :
是KVO的一部分, 源文件的代码为:
用了这两个方法也就代表手动触发了KVO, 这也为了控制回调的调用时机, 在setPullToRefreshView:
中触发. 而手动触发的场景一般是不使用属性,或重写了setter,需要手动通知系统.
一般我们是不需要用的, 比如@property
写一个属性, 系统会以某种方式在中间插入 wilChangeValueForKey:
, didChangeValueForKey:
和 observeValueForKeyPath:ofObject:change:context:
的调用.
想要了解更多, 可以看一下
KVO Programming Guide - Apple官方文档
关于runtime:
这里要知道这两个方法:
看完所有API, 其实也了解的差不多, 这样就给scrollView增加了一个SVPullToRefreshView
类型的属性;
3.1.3 监听探究
这里主要涉及scrollView的三个监听, contentOffset
, contentSize
, frame
;frame
就不用说了, 说一下另外两个;contentOffset
是scrollview当前显示区域顶点相对于frame顶点的偏移量。可以理解为contentview的顶点相对于scrollerVIew的frame的偏移量;contentSize
是scrollview当前所有内容区域的大小;
顺便提下contentInset
, 下面用到, 表示contentView.frame与scrollerView.frame的关系, 可以类比于css里的padding.
例如:
则testScrollView的top, left, bottom, right为10;
好了, 现在到重头戏了, 监听如何执行的, 代码如下:
可以理解为当监听contentOffset
改变时, scrollView滚动, 此时执行scrollViewDidScroll:
方法得到此时的滚动state; 当为contentSize
和frame
时, scrollView视图发生变化, 此时执行layoutSubviews
重新加载视图, 包括根据状态改变视图样式, 都在这里面执行;scrollViewDidScroll:
方法:
可以看出根据postion位置, state是SVPullToRefreshStateLoading状态的时候, 改变scrollView的contentInset;非该状态的时候, 根据contentOffset和postion设置state;
下拉刷新后, scrollView的内容高度下移60; 当然只是内容高度, 整个scrollView还是全屏的, 对比css中padding理解一下;
注:
SVPullToRefreshView
向右移动一点儿距离, 方便看视图层级;
layoutSubviews
方法:
self.viewForState
为一个可变数组, 里面是而且根据状态装入相应state的customView, 首先从通过- (void)setCustomView:forState:
方法添加后removeFromSuperview
从父视图剥离, 之后根据是否传入了customView决定是否添加自定义视图; 如果没有customView则改变里面arrowView的角度;最后都得改变titleLabel
, subtitleLabel
, arrow
, activityIndicatorView
的尺寸或位置;
值得注意的是里面的一个方法暴露了demo的年纪, O(∩_∩)O哈哈~
7.0之后已取消, 难怪我感觉没见过这个方法. 哎, 还是太年轻~
3.2 上拉刷新
话不多说, 先看东西…(此话出自老罗语录😊)
上拉刷新相对于下拉, 少了很多东西, 也就简单了一些, 重复性的就不多说了.值得注意的是, 对比下拉, 上拉把layoutSubviews
里面东西放到setState:
里面. 也是, 毕竟没多少东西, 对比着下拉刷新来看;
4.总结
这次阅读源码,可以说收获满满啊。以前觉得源码阅读是个比较枯燥的过程,可是当我把一个个问题解决了之后,成就感也慢慢累积,感觉就是越读越来劲儿。而且发现读一遍是远远不够的,每看了一遍都多少会有些收获。慢慢的从(这个方法是干什么的)–>(为什么写这个方法)–>(为什么写在这里),等等一些思考。在对作者称赞👍的同时也为自己认识了这种方法而感到高兴。
再接再厉!!!
加油💪2017!!!
想要了解更多的内容, 可以关注一下我的个人公众号。该公众号每个工作日会有新闻推送,每周技术分享,博客更新会实时推送。做个有态度的iOS开发者,就从身边的一件件小事儿做起。满满的正能量,有没有?Do you get it?