MJRefresh的二次封装

平常用的刷新用是开源的MJRefresh,这个刷新库想必也是很多开发者比较熟悉的一个库,作者采用继承的方式,不同的层次有不同的功能与UI展示,用起来简洁,方便。


MJ为UIScrollView类写了类别,给UIScrollView增加了mj_header(下拉刷新)和mj_footer(上拉加载更多)两个关联对象。 MJ作者李明杰老师的示例用法如下:

  • 下拉刷新
  __weak typeof(self) weakSelf = self;
    self.tableView.mj_header = [MJRefreshHeader headerWithRefreshingBlock:^{
        [weakSelf refreshAction];//这里可以做请求网络等操作。
    }];
    刷新的操作结束后,调用下边方法,结束刷新
    [self.tableView.mj_header endRefreshing];
复制代码
  • 上拉加载更多
    __weak typeof(self) weakSelf = self;
    self.tableView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{
        [weakSelf footerRefreshAction];//请求更多数据
    }];
    //可以根据请求的结果来以不同的方式结束刷新。
     [self.tableView.mj_footer endRefreshing];
    [self.tableView.mj_footer endRefreshingWithNoMoreData];
    
复制代码

以上只是示例,MJ中作者提供来多种不同UI和交互的header和footer供大家选择使用。

平常这样直接按照作者的Demo示例用可以,但是个人总觉得不太好。就想着能够封装下(主要是懒,想省点事)。

先说下基本的需求:一个tableView的列表,每页请求20(注:不同的公司可能不同的每页条数,这里只是举例)条数据,下拉刷新的时候是重新请求第一页的数据,上拉加载更多的时候是请求下一页数据。如果下一页数据还是20条,则认为还有数据,将footr以正常的状态结束刷新。再次上拉加载的时候,还会正常请求下一页的数据。 如果加载出来的数据少于一页的数据条数(20条),那么就认为没有更多数据了,这时就将footer以没有更多数据的状态结束刷新,再进行上拉加载的时候,将不起作用。

我想要的效果是,我外部调用的时候,我只想知道触发去请求刷新和加载更多的时机, 其它的都不想管。

本人目前的实现是:给UITableView写了一个类别(UICollectionView同理。UIScrollView也可以进行下拉刷新,只不过是不用上拉加载更多了)。写了两个方法,分别是下拉刷新和上拉加载的调用。同时增加了两个关联对象:每页的数据条数和一个上拉加载更多后的footer的设置回调的block。 示例代码如下:

#define WeakSelf __weak typeof(self) weakSelf = self;

typedef void(^FooterConfigBlock)(NSInteger newDataCount);
typedef void(^RefreshActionBlock)(FooterConfigBlock footerConfig);
@interface UITableView (Refresh)
/**
 每页的数据条数
*/
@property (nonatomic,strong)NSNumber *pageCount;

/**
 设置footer的回调
 */
@property (nonatomic,copy)void(^footerConfigBlock)(NSInteger newCount);

/**
 header的刷新

 @param refreshBlock 刷新的回调,回调block里有个"FooterConfigBlock"的参数,外部调用的时候可以将请求下拉的数据的条数传进来,让方法里边对footer进行设置。eg:如果下拉刷新都没有数据的话,就可以直接将不要footer。
 */
- (void)normalHeaderRefreshingActionBlock:(RefreshActionBlock)refreshBlock;

/**
 footer的刷新加载更多

 @param footerRefreshBlock 加载更多的回调。回调block里有个"FooterConfigBlock"的参数,外部调用的时候可以将请求下拉的数据的条数传进来,让方法里边对footer进行设置。eg:如果上拉加载返回的数据小于每页的设置条目数量,则认为数据已经加载完毕,可以将footer设置为没有更多数据的状态。
 */
- (void)backNormalFooterRefreshingActionBlock:(RefreshActionBlock)footerRefreshBlock;

@end


@implementation UITableView (Refresh)
#pragma mark --关联对象----------------
- (void)setPageCount:(NSNumber *)pageCount
{
    objc_setAssociatedObject(self, @selector(setPageCount:), pageCount, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSNumber *)pageCount
{
    return objc_getAssociatedObject(self, @selector(setPageCount:));
}

- (void)setFooterConfigBlock:(void (^)(NSInteger))footerConfigBlock
{
    objc_setAssociatedObject(self, @selector(setFooterConfigBlock:), footerConfigBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (void (^)(NSInteger))footerConfigBlock
{
    return objc_getAssociatedObject(self, @selector(setFooterConfigBlock:));
}


#pragma mark --header刷新----------------

- (void)normalHeaderRefreshingActionBlock:(RefreshActionBlock)refreshBlock
{
//如果外部调用的时候不设置每页的数据条目数量pageCount。这里设置一个默认值。
    self.pageCount = [self.pageCount integerValue] > 0 ? self.pageCount : @(20);
    WeakSelf
    //将外部的block给关联对象赋值,如果外部需要内部进行footer和header结束刷新的处理的话,可以传block进来。
    self.footerConfigBlock = ^(NSInteger newCount) {
        [weakSelf handleEndRefreshing:newCount];
    };
    self.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
        refreshBlock(weakSelf.footerConfigBlock);
    }];
}
#pragma mark --footer刷新----------------
- (void)backNormalFooterRefreshingActionBlock:(RefreshActionBlock)footerRefreshBlock
{
//同理设置一个默认的每页数据条目
    self.pageCount = [self.pageCount integerValue] > 0 ? self.pageCount : @(20);
    WeakSelf
    self.footerConfigBlock = ^(NSInteger newCount) {
        [weakSelf handleEndRefreshing:newCount];
    };
    
    self.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{
        footerRefreshBlock(weakSelf.footerConfigBlock);
    }];
}

- (void)handleEndRefreshing:(NSInteger)count
{
    if (self.mj_header.isRefreshing) {
        [self.mj_header endRefreshing];
        [self.mj_footer endRefreshing];
    }
    
    if (count < [self.pageCount integerValue]) {
        [self.mj_footer endRefreshingWithNoMoreData];
    }else{
        [self.mj_footer endRefreshing];
    }
}

#pragma mark --结束刷新-----
//如果外部想自己处理结束刷新,可以为tabelView添加的其它结束刷新的方法。
- (void)beginRefreshing
{
    if (!self.mj_header) return;
    [self.mj_header beginRefreshing];
}

- (void)endRefrehing
{
    if (self.mj_header) {
        [self.mj_header endRefreshing];
    }
    if (self.mj_footer) {
        [self.mj_footer endRefreshing];
    }
}
@end
复制代码

外部的调用如下:

- (void)configTableView
{
    WeakSelf
    [self.tableView normalHeaderRefreshingActionBlock:^(FooterConfigBlock  _Nonnull footerConfig) {
        weakSelf.page = 1;
        //上拉刷新触发请求第一页数据。
        [weakSelf requestData:^(NSInteger count) {
            weakSelf.dataCount = count;
            [weakSelf.tableView reloadData];
            //请求成功后将数据的条数回调给tableView,让tableVie自己处理footer的设置
            footerConfig(count);
        } failCallBack:^{
            [weakSelf.tableView endRefrehing];
        }];
    }];

    [self.tableView backNormalFooterRefreshingActionBlock:^(FooterConfigBlock  _Nonnull footerConfig) {
        [weakSelf requestData:^(NSInteger count) {
            weakSelf.dataCount += count;
            [weakSelf.tableView reloadData];
            //请求成功后将数据的条数回调给tableView,让tableVie自己处理footer的设置
            footerConfig(count);
        } failCallBack:^{
            [weakSelf.tableView endRefrehing];
        }];
    }];
    
    [self.tableView beginRefreshing];
}

- (void)requestData:(void(^)(NSInteger count))successCallBack failCallBack:(void(^)(void))failCallBack
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
        if (self.page > 5) {
            successCallBack(0);
        }else{
            successCallBack(20);
        }
        self.page += 1;
    });
}

复制代码

以上只是自己的简单封装示例,MJRefresh提供了多种header和footer,可以根据业务或产品的要求自定义并封装适合自己的使用代码。

以上是本人的一些使用总结,如有错误,还请批评指正。谢谢!!!

转载于:https://juejin.im/post/5d025fb2e51d45773f2e8f41

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值