IOSios实用开发技巧iOS开发

iOS 轻松实现页面无数据、无网络、请求出错的友好提示

2017-08-18  本文已影响2184人  AceKitty

本文主要是讲讲自己在项目中基于 MJRefresh 封装的一套当页面出现异常情况时给出友好提示页面 YYLrefresh 的实现思路。
Github下载地址: YYLrefresh

实现思路

  1. 采用低侵入式的 category来实现。
    • category不需要通过增加子类而增加现有类的行为(方法), 且类目中的方法与原始类方法基本没有区别。
    • 通过 category 可以将庞大一个类的方法进行划分,从而便于代码的日后的维护、更新以及提高代码的阅读性。
  2. 采用插座式的设计无数据、无网络、请求出错页面方便产品的个性化需求,并且提供默认实现。

具体实现

代码目录.png

下面先来看具体实现的头文件UIScrollView+Refresh.h

  1. 首先定义一个枚举用来区分当前页面的类型
typedef enum : NSUInteger {
    YYLLoadErrorTypeDefalt,
    YYLLoadErrorTypeNoNetwork,      //没有网络
    YYLLoadErrorTypeRequest,        //请求接口 后台报错
    YYLLoadErrorTypeNoData,         //当前页面没有数据
} RELoadErrorType;
  1. 下面定义的属性,主要是用来决定用 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;
  1. 下面属性主要是用来设置页面显示的类型
/**
 *  设置页面显示的类型
 */
@property(nonatomic, assign) RELoadErrorType loadErrorType;

/**
 *  数据是否全部加载完
 */
@property(nonatomic, assign) BOOL isDataLoaded;

/**
 是否第一次加载
 */
@property(nonatomic, assign) BOOL isFirstLoading;

/**
 *  停止刷新
 */
- (void)endRefreshing;
  1. 下面是默认的无数据、无网络、请求出错页面提示,可以根据产品的需求替换成自己实现的 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 来决定该怎样显示页面: 具体实现是将原来的页面上显示的辅助视图移除掉,根据类型显示新的视图。新视图的位置大小与页面相同。

上一篇 下一篇

猜你喜欢

热点阅读