本文主要是讲讲自己在项目中基于 MJRefresh 封装的一套当页面出现异常情况时给出友好提示页面 YYLrefresh 的实现思路。
Github下载地址: YYLrefresh
实现思路
- 采用低侵入式的 category来实现。
- category不需要通过增加子类而增加现有类的行为(方法), 且类目中的方法与原始类方法基本没有区别。
- 通过 category 可以将庞大一个类的方法进行划分,从而便于代码的日后的维护、更新以及提高代码的阅读性。
- 采用插座式的设计无数据、无网络、请求出错页面方便产品的个性化需求,并且提供默认实现。
具体实现
代码目录.png下面先来看具体实现的头文件UIScrollView+Refresh.h
- 首先定义一个枚举用来区分当前页面的类型
typedef enum : NSUInteger {
YYLLoadErrorTypeDefalt,
YYLLoadErrorTypeNoNetwork, //没有网络
YYLLoadErrorTypeRequest, //请求接口 后台报错
YYLLoadErrorTypeNoData, //当前页面没有数据
} RELoadErrorType;
- 下面定义的属性,主要是用来决定用 UIScrollView、UITableView...及其子类实现的页面是否显示下拉刷新,上啦加载功能及其回调 Block。
/**
* 是否显示表格的头部刷新
*/
@property(nonatomic, assign) BOOL isShowHeaderRefresh;
/**
* 是否显示表格的尾部刷新
*/
@property(nonatomic, assign) BOOL isShowFooterRefresh;
/**
* 表格头部刷新调用的Block
*/
@property(nonatomic, copy) RERefreshTableViewRefreshingBlock headerRefreshingBlock;
/**
* 表格尾部刷新调用的Block
*/
@property(nonatomic, copy) RERefreshTableViewRefreshingBlock footerRefreshingBlock;
- 下面属性主要是用来设置页面显示的类型
/**
* 设置页面显示的类型
*/
@property(nonatomic, assign) RELoadErrorType loadErrorType;
/**
* 数据是否全部加载完
*/
@property(nonatomic, assign) BOOL isDataLoaded;
/**
是否第一次加载
*/
@property(nonatomic, assign) BOOL isFirstLoading;
/**
* 停止刷新
*/
- (void)endRefreshing;
- 下面是默认的无数据、无网络、请求出错页面提示,可以根据产品的需求替换成自己实现的 View。 具体使用见项目中的 Demo 实现。
/**
* 没有网络时显示的视图
*/
@property(nonatomic, strong) UIView *refreshNoNetworkView;
/**
* 访问出错时显示的视图
*/
@property(nonatomic, strong) UIView *refreshRequestErrorView;
/**
* 没有数据显示的视图
*/
@property(nonatomic, strong) UIView *refreshNoDataView;
/**
* 错误视图的tableview容器
*/
@property(nonatomic, strong) UITableView *refreshErrorTableView;
UIScrollView+Refresh.m 具体实现代码的详解:
.m 文件主要是重写 .h文件中的各个属性的 get 和 set 方法, 然后借助 objc_setAssociatedObject
将属性关联上对象。具体实现这里就不一一解释了。主要来看一下下面这个核心的方法实现:
- (void)setLoadErrorType:(YYLLoadErrorType)loadErrorType {
if (self.refreshNoNetworkView.superview) [self.refreshNoNetworkView removeFromSuperview];
if (self.refreshRequestErrorView.superview) [self.refreshRequestErrorView removeFromSuperview];
if (self.refreshNoDataView.superview) [self.refreshNoDataView removeFromSuperview];
if (loadErrorType == YYLLoadErrorTypeNoNetwork) {
self.isShowFooterRefresh = NO;
[self addSubview:self.refreshNoNetworkView];
[self.refreshNoNetworkView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(0);
make.width.mas_equalTo(self.mas_width);
make.top.mas_equalTo(0);
make.height.mas_equalTo(self.mas_height);
}];
} else if (loadErrorType == YYLLoadErrorTypeRequest) {
self.isShowFooterRefresh = NO;
[self addSubview:self.refreshRequestErrorView];
[self.refreshRequestErrorView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(0);
make.width.mas_equalTo(self.mas_width);
make.top.mas_equalTo(0);
make.height.mas_equalTo(self.mas_height);
}];
} else if (loadErrorType == YYLLoadErrorTypeNoData) {
self.isShowFooterRefresh = NO;
[self addSubview:self.refreshNoDataView];
[self.refreshNoDataView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(0);
make.width.mas_equalTo(self.mas_width);
make.top.mas_equalTo(0);
make.height.mas_equalTo(self.mas_height);
}];
}
objc_setAssociatedObject(self, &loadErrorTypeKey, @(loadErrorType), OBJC_ASSOCIATION_ASSIGN);
[self endRefreshing];
}
这个方法主要是通过用户设置的类型 loadErrorType
来决定该怎样显示页面: 具体实现是将原来的页面上显示的辅助视图移除掉,根据类型显示新的视图。新视图的位置大小与页面相同。
网友评论