MJRefresh实现原理
大家常用的UITableView UIClollectionView上拉 下拉加载数据很常见。
以下分析MJRefresh实现方法
首先看下,框架是如何使用的,只需如下2行代码即可实现下拉加载数据
self.collectionView.header = [MJRefreshNormalHeaderheaderWithRefreshingTarget:selfrefreshingAction:@selector(loadNewData)];
[self.collectionView.headerbeginRefreshing];
对此肯定很多同学不理解,2行代码是怎么实现的呢,它是怎么控collectionView下拉,松手后调用loadNewData这个方法呢?
首先请看UITableView UIClollectionView是继承自UIScrollView的,他们是没有header这个属性的。(header是自定义的一个UIView)
要想给即有的类动态增加一个属性当然要写个分类用到运行时了,请看如下代码:
.h文件
@class MJRefreshHeader;
@interface UIScrollView (MJRefresh)
@property (strong,nonatomic) MJRefreshHeader *header;
@end
.m实现文件
@implementation UIScrollView (MJRefresh)
static constchar MJRefreshHeaderKey = '\0';
- (void)setHeader:(MJRefreshHeader *)header
{
if (header !=self.header) {
// 删除旧的,添加新的
[self.headerremoveFromSuperview];
[selfaddSubview:header];
objc_setAssociatedObject(self, &MJRefreshHeaderKey,
header, OBJC_ASSOCIATION_ASSIGN);
}
}
- (MJRefreshHeader *)header
{
returnobjc_getAssociatedObject(self, &MJRefreshHeaderKey);
}
以上代码的作用是给继承自 UIScrollView的类动态增加了一个自定义的header属性[self addSubview:header];这个self其实就是调用者本身即self.collectionView现在就有了一个自定义的header被加在了self.collectionView上了
但又是如何控制collectionView下拉后,header显示并调用加载数据方法呢?至少得要知道,下拉时ContentOffset.Y的偏移量吧,但是怎么拿到呢。
答案是在header被添加到self.collectionView时,在header这个类中重写了
- (void)willMoveToSuperview:(UIView *)newSuperview//在一个子视图将要被添加到另一个视图的时候发送此消息
这个newSuperview就是self.collectionView,这时只需中header中申明一个成员变理__weakUIScrollView *_scrollView;/** 父控件 */
_scrollView=newSuperview
利用KVO去监听ContentOffset这个值的改变,
[self.scrollViewaddObserver:selfforKeyPath:@"contentOffset"options:optionscontext:nil];
下面就是监听contentOffset值的变化,做相应处理,最后调用objc_msgSend(self.refreshingTarget, self.refreshingAction,self);刷新
原理大概就是这样,当然实际写的时候里面细节有很多,还是很佩服MJ老师的^_^。