美文网首页
MJRefresh源码研究

MJRefresh源码研究

作者: tangbin583085 | 来源:发表于2017-08-19 16:43 被阅读0次

    今天终于有空揭开了MJRefresh源码的神秘面纱

    结构:

    1,MJRefreshComponent继承UIView,是所有刷新控件的基类。
    2,MJRefreshHeader继承MJRefreshComponent,是所有头部刷新的基类。
    3,MJRefreshFooter继承MJRefreshComponent,是所有尾部刷新的基类。尾部刷新分为auto和back2种方式,MJRefreshAutoFooter,MJRefreshBackFooter均继承MJRefreshFooter。

    MJRefresh实现原理:

    1,MJRefreshHeader / MJRefreshFooter添加到ScrollView

    - (void)setMj_header:(MJRefreshHeader *)mj_header
    {
        if (mj_header != self.mj_header) {
            // 删除旧的,添加新的
            [self.mj_header removeFromSuperview];
            [self insertSubview:mj_header atIndex:0];
            
            // 存储新的
            [self willChangeValueForKey:@"mj_header"]; // KVO
            objc_setAssociatedObject(self, &MJRefreshHeaderKey,
                                     mj_header, OBJC_ASSOCIATION_ASSIGN);
            [self didChangeValueForKey:@"mj_header"]; // KVO
        }
    }
    

    设置并获取父类scrollView相应属性(MJRefreshComponent)

    - (void)willMoveToSuperview:(UIView *)newSuperview
    {
        [super willMoveToSuperview:newSuperview];
        
        // 如果不是UIScrollView,不做任何事情
        if (newSuperview && ![newSuperview isKindOfClass:[UIScrollView class]]) return;
        
        // 旧的父控件移除监听
        [self removeObservers];
        
        if (newSuperview) { // 新的父控件
            // 设置宽度
            self.mj_w = newSuperview.mj_w;
            // 设置位置
            self.mj_x = 0;
            
            // 记录UIScrollView
            _scrollView = (UIScrollView *)newSuperview;
            // 设置永远支持垂直弹簧效果
            _scrollView.alwaysBounceVertical = YES;
            // 记录UIScrollView最开始的contentInset
            _scrollViewOriginalInset = _scrollView.contentInset;
            
            // 添加监听
            [self addObservers];
        }
    }
    

    2,利用KVO监听UISrollView的ContentOffset,ContentSize,panGestureRecognizer的变化作相应的状态处理。(重点,核心)
    关键代码:(MJRefreshComponent)

    #pragma mark - KVO监听
    - (void)addObservers
    {
        NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
        [self.scrollView addObserver:self forKeyPath:MJRefreshKeyPathContentOffset options:options context:nil];
        [self.scrollView addObserver:self forKeyPath:MJRefreshKeyPathContentSize options:options context:nil];
        self.pan = self.scrollView.panGestureRecognizer;
        [self.pan addObserver:self forKeyPath:MJRefreshKeyPathPanState options:options context:nil];
    }
    

    这些属性一但变化到一定值就调用相应的方法处理,比如头部下拉刷新:

    
    - (void)scrollViewContentOffsetDidChange:(NSDictionary *)change
    {
        [super scrollViewContentOffsetDidChange:change];
        // 偏移量一旦达到一定值就调用相应方法
        ......
    }
    

    3,运行时
    设置/获取 header/footer

    
    // 存储
    [self willChangeValueForKey:@"mj_header"]; // KVO
    objc_setAssociatedObject(self, &MJRefreshHeaderKey,
                                     mj_header, OBJC_ASSOCIATION_ASSIGN);
    [self didChangeValueForKey:@"mj_header"]; // KVO
    
    // 获取
    return objc_getAssociatedObject(self, &MJRefreshHeaderKey);
    
    

    执行taget 的selector

    #pragma mark - 内部方法
    - (void)executeRefreshingCallback
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (self.refreshingBlock) {
                self.refreshingBlock();
            }
            if ([self.refreshingTarget respondsToSelector:self.refreshingAction]) {
                MJRefreshMsgSend(MJRefreshMsgTarget(self.refreshingTarget), self.refreshingAction, self);
            }
            if (self.beginRefreshingCompletionBlock) {
                self.beginRefreshingCompletionBlock();
            }
        });
    }
    

    4,补充重写
    自己重写继承相应的父类,主要重写以下3个方法就OK了

    #pragma mark - 覆盖父类的方法
    // 准备初始化工作,如添加不同状态的文字显示
    - (void)prepare
    {
        [super prepare];
    }
    
    // 布局自定的控件
    - (void)placeSubviews
    {
        [super placeSubviews];
    }
    
    // 不同状态的处理
    - (void)setState:(MJRefreshState)state
    {
        MJRefreshCheckState
    }
    

    相关文章

      网友评论

          本文标题:MJRefresh源码研究

          本文链接:https://www.haomeiwen.com/subject/scuvrxtx.html