一.问题

对于B2C和B2B项目的开发者,可能会有一个订单列表为空,或者其他收藏页面为空,用户token失效,判断用户要重新登陆,以及后台服务错误等提示。本篇课文,看完大约10分钟。

原本自己不想写空页面的展示,网络加载失败或者重新登陆的封装,想从网上找一个第三方的view,但找了很多都是让我继承他人的控制器,而我自己写好了继承基本的控制器,如果继承他人的控制器,自己的代码需要改比较多的地方,所以决定自己写(如果其他开发者,也有同样的困扰,可以直接复用,不需要继承)

 二.不谈虚的,直接上源代码

1.首先写一个协议,以后view布局遵守此协议,实现其方法实现布局。

#import <Foundation/Foundation.h>

@protocol IOAProtocol <NSObject>
@optional
// 需要 [super addSubViews]
- (void)addSubViews;
// 不需要[super prepare] 用作布局
- (void)prepare; @end

 2.订单空页面的UI

#import <UIKit/UIKit.h>
#import "IOAProtocol.h" @interface IOAEmptyPageView : UIView <IOAProtocol>//遵守协议
@property (nonatomic, readonly, strong) UIImageView *imageView;
@property (nonatomic, readonly, strong) UILabel *titleLabel;
@property (nonatomic, readonly, strong) UILabel *subTitleLabel;
//可能有的空页面需要点击一下跳转(备用)
@property (nonatomic, readonly, strong) UIButton *refreshButton; @property (nonatomic, copy) void (^clickCallback)(id object);
@end

.m文件

#import "IOAEmptyPageView.h"

@interface IOAEmptyPageView ()
@property (nonatomic, readwrite, strong) UIImageView *imageView;
@property (nonatomic, readwrite, strong) UILabel *titleLabel;
@property (nonatomic, readwrite, strong) UILabel *subTitleLabel;
@property (nonatomic, readwrite, strong) UIButton *refreshButton; @end @implementation IOAEmptyPageView
- (void)dealloc { } - (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor whiteColor];
[self addSubViews];
[self prepare];
} return self;
} - (void)addSubViews {
[self addSubview:self.imageView];
[self addSubview:self.titleLabel];
[self addSubview:self.subTitleLabel];
[self addSubview:self.refreshButton];
} //利用masonry进行适配
- (void)prepare { [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self);
make.bottom.equalTo(self.mas_centerY).offset(-);
make.left.greaterThanOrEqualTo(self);
make.right.lessThanOrEqualTo(self);
}]; [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.imageView);
make.top.equalTo(self.imageView.mas_bottom).offset();
make.left.greaterThanOrEqualTo(self);
make.right.lessThanOrEqualTo(self);
make.height.equalTo(@);
}]; [self.subTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.titleLabel);
make.top.equalTo(self.titleLabel.mas_bottom).offset();
make.left.greaterThanOrEqualTo(self);
make.right.lessThanOrEqualTo(self);
make.height.equalTo(@);
}]; [self.refreshButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self.subTitleLabel);
make.top.equalTo(self.subTitleLabel.mas_bottom).offset();
// make.left.greaterThanOrEqualTo(self);
// make.right.lessThanOrEqualTo(self);
make.height.equalTo(@);
make.width.equalTo(@);
}];
} #pragma mark - Actions
- (void)clickedRefreshButton:(id)button {
if (self.clickCallback) {
self.clickCallback(self);
}
} #pragma mark - Setter / Getter
- (UIImageView *)imageView {
if (!_imageView) {
_imageView = [UIImageView new];
_imageView.contentMode = UIViewContentModeCenter;
_imageView.image = [UIImage imageNamed:@"EmptyImage"];
} return _imageView;
} - (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [UILabel new];
_titleLabel.textColor = RGB_HEXString(@"#323232");
_titleLabel.font = [UIFont systemFontOfSize:];
_titleLabel.textAlignment = NSTextAlignmentCenter;
} return _titleLabel;
} - (UILabel *)subTitleLabel {
if (!_subTitleLabel) {
_subTitleLabel = [UILabel new];
_subTitleLabel.textColor = RGB_HEXString(@"#323232");
_subTitleLabel.font = [UIFont systemFontOfSize:];
_subTitleLabel.textAlignment = NSTextAlignmentCenter;
} return _subTitleLabel;
} - (UIButton *)refreshButton {
if (!_refreshButton) {
_refreshButton = [UIButton buttonWithType:UIButtonTypeSystem];
[_refreshButton setTitle:@"重新加载" forState:UIControlStateNormal];
[_refreshButton setTitleColor:RGB_HEXString(@"#323232") forState:UIControlStateNormal];
_refreshButton.titleLabel.font = [UIFont systemFontOfSize:];
[_refreshButton addTarget:self action:@selector(clickedRefreshButton:) forControlEvents:UIControlEventTouchUpInside];
_refreshButton.layer.cornerRadius = ;
_refreshButton.layer.borderColor = RGB_HEXString(@"#323232").CGColor;
_refreshButton.layer.borderWidth = 1.0f;
} return _refreshButton;
}
@end

封装调用方法(无数据提示,无数据跳转,后台服务错误以及token失效,请重新登陆)

#import <UIKit/UIKit.h>
#import "IOAEmptyPageView.h" @interface UIViewController (Progress)
- (void)startProgress;
- (void)stopProgress; - (void)startProgress:(BOOL)animate;
- (void)stopProgress:(BOOL)animate; // 提示框
- (void)showAlertWithTitle:(NSString *)title detail:(NSString *)deatil clickBlock:(void (^)(NSInteger index))clickBlock;
- (void)showCommonAlertWithTitle:(NSString *)title clickBlock:(void(^)(NSInteger index))clickBlock;
//- (void)hideCommonAlert; // 无网络
- (UIView *)showNoNetworkPage;
- (void)dismissNoNetworkPage;
//- (void)clickedNoNetworkPage:(id)object; // 空页面
- (UIView *)showNoDatasPage;
- (void)dismissNoDatasPage;
//订单空页面的提示(目前我用的)
- (UIView *)showNoOrderPage:(NSString *)str withImage:(NSString *)image;
//- (void)clickedNoDatasPage:(id)object; // 服务后台错误
- (UIView *)showServerErrorPage;
- (void)dismissServerErrorPage; - (UIView *)showEmptyPageWith:(UIImage *)image title:(NSString *)title subTitle:(NSString *)subTitle;
- (void)dismissEmptyPage;
- (void)clickedEmptyPage:(id)object; // token 失效 push
// 先弹出当前VC
- (void)showLoginViewController;
// 不弹出当前VC
- (void)showLoginViewControllerNoPop;
/*
* 跳转到登录界面
* @paramater isNeedPopCurVC: YES 要弹出当前VC NO 不需要弹出
*/
- (void)showLoginViewcontrollerWithPopCurrentVC:(BOOL)isNeedPopCurVC;
@end

.m文件实现

#import "UIViewController+Progress.h"
//借助第三方
#import <MBProgressHUD/MBProgressHUD.h>
#import <MMPopupView/MMAlertView.h>
//用户登陆控制器(导入你们自己的loginVc)
#import "IOAUserLoginViewController.h" @implementation UIViewController (Progress)
- (void)startProgress {
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
}
- (void)stopProgress {
[MBProgressHUD hideHUDForView:self.view animated:YES];
} - (void)startProgress:(BOOL)animate {
[MBProgressHUD showHUDAddedTo:self.view animated:animate];
}
- (void)stopProgress:(BOOL)animate {
[MBProgressHUD hideHUDForView:self.view animated:NO];
} - (void)showAlertWithTitle:(NSString *)title detail:(NSString *)deatil clickBlock:(void (^)(NSInteger index))clickBlock {
NSArray *items =
@[
MMItemMake(@"取消", MMItemTypeNormal, clickBlock),
MMItemMake(@"确定", MMItemTypeHighlight, clickBlock)]; MMAlertView *alertView = [[MMAlertView alloc] initWithTitle:title detail:deatil items:items];
// alertView.attachedView = self.view;
alertView.attachedView.mm_dimBackgroundBlurEnabled = NO;
alertView.attachedView.mm_dimBackgroundBlurEffectStyle = UIBlurEffectStyleLight; [alertView show];
} - (void)showCommonAlertWithTitle:(NSString *)title clickBlock:(void(^)(NSInteger index))clickBlock {
[self showAlertWithTitle:title detail:nil clickBlock:clickBlock];
} // 无网络
- (UIView *)showNoNetworkPage {
return [self showEmptyPageWith:nil title:@"网络请求失败" subTitle:@"请检查网络"];
}
- (void)dismissNoNetworkPage {
[self dismissEmptyPage];
} // 空页面
- (UIView *)showNoDatasPage { return [self showEmptyPageWith:nil title:@"网络请求成功" subTitle:@"数据为空"];
} //无订单---主要用的
- (UIView *)showNoOrderPage:(NSString *)str withImage:(NSString *)image{
return [self showEmptyOrderWith:[UIImage imageNamed:image] title:nil subTitle:str];
} - (void)dismissNoDatasPage {
[self dismissEmptyPage];
} - (UIView *)showServerErrorPage {
return [self showEmptyPageWith:nil title:@"网络请求失败" subTitle:@"后台服务错误"];
}
- (void)dismissServerErrorPage {
[self dismissEmptyPage];
} - (UIView *)showEmptyPageWith:(UIImage *)image title:(NSString *)title subTitle:(NSString *)subTitle {
for (UIView *view in self.view.subviews) {
if ([view isKindOfClass:[IOAEmptyPageView class]]) {
return view;
}
}
IOAEmptyPageView *emptyView = [IOAEmptyPageView new];
// emptyView.backgroundColor = [UIColor redColor];
if (image) {
emptyView.imageView.image = image;
}
emptyView.titleLabel.text = title;
emptyView.subTitleLabel.text = subTitle;
WS(weakSelf);
emptyView.clickCallback = ^(id object) {
[weakSelf clickedEmptyPage:weakSelf];
[weakSelf dismissEmptyPage];
};
[self.view addSubview:emptyView];
UINavigationBar *navBar = self.navigationController.navigationBar;
UITabBar *tarBar = self.tabBarController.tabBar; CGFloat topOffset = ;
CGFloat bottomOffset = ;
if (!navBar.hidden) {
topOffset = TopHeightOffset;
}
if (!tarBar.hidden) {
bottomOffset = BottomHeightOffset;
} [emptyView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.view);
make.top.equalTo(self.view).offset(topOffset);
make.bottom.equalTo(self.view).offset(-bottomOffset);
}];
return emptyView;
} - (UIView *)showEmptyOrderWith:(UIImage *)image title:(NSString *)title subTitle:(NSString *)subTitle {
for (UIView *view in self.view.subviews) {
if ([view isKindOfClass:[IOAEmptyPageView class]]) {
return view;
}
}
IOAEmptyPageView *emptyView = [IOAEmptyPageView new];
if (image) {
emptyView.imageView.image = image;
}
emptyView.titleLabel.text = title;
emptyView.subTitleLabel.text = subTitle;
emptyView.refreshButton.hidden = YES;
WS(weakSelf);
emptyView.clickCallback = ^(id object) {
[weakSelf clickedEmptyPage:weakSelf];
[weakSelf dismissEmptyPage];
};
[self.view addSubview:emptyView];
UINavigationBar *navBar = self.navigationController.navigationBar;
UITabBar *tarBar = self.tabBarController.tabBar; CGFloat topOffset = ;
CGFloat bottomOffset = ;
if (!navBar.hidden&&![subTitle isEqualToString:@"你还没有收藏的商品"]) {
topOffset = TopHeightOffset;
}
if (!tarBar.hidden) {
bottomOffset = BottomHeightOffset;
} [emptyView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.view);
make.top.equalTo(self.view).offset(topOffset);
make.bottom.equalTo(self.view).offset(-bottomOffset);
}];
return emptyView;
} - (void)dismissEmptyPage {
for (UIView *view in self.view.subviews) {
if ([view isKindOfClass:[IOAEmptyPageView class]]) {
[view removeFromSuperview];
return;
}
}
}
- (void)clickedEmptyPage:(id)object {
[self dismissEmptyPage];
} // token 失效 push
- (void)showLoginViewController {
[self showLoginViewcontrollerWithPopCurrentVC:YES];
} // 不弹出当前VC
- (void)showLoginViewControllerNoPop {
[self showLoginViewcontrollerWithPopCurrentVC:NO];
} - (void)showLoginViewcontrollerWithPopCurrentVC:(BOOL)isNeedPopCurVC {
if (!self.navigationController) return; IOAUserLoginViewController *loginVC = [IOAUserLoginViewController new];
NSMutableArray *array = [NSMutableArray array];
NSArray *vcList = self.navigationController.viewControllers;
if ([[vcList lastObject] isKindOfClass:[IOAUserLoginViewController class]]) {
return;
}
[array addObjectsFromArray:vcList];
if (array.count > && isNeedPopCurVC) {
[array removeLastObject];
}
[array addObject:loginVC];
[self.navigationController setViewControllers:array animated:YES];
} #if 0
UIAlertController *alert = [UIAlertController alertControllerWithTitle:number message:@"拨打电话" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) { }];
UIAlertAction *no = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { }]; unsigned int count = ;
Ivar *ivars = class_copyIvarList([UIAlertController class], &count);
for(int i = ; i<count; i ++) {
Ivar ivar = ivars[i];
NSString *ivarName = [NSString stringWithCString:ivar_getName(ivar) encoding:NSUTF8StringEncoding]; //标题颜色
if ([ivarName isEqualToString:@"_attributedTitle"]) {
NSMutableAttributedString *attr = [[NSMutableAttributedString alloc]initWithString:alert.title attributes:@{NSForegroundColorAttributeName:RGB_HEXString(@"#323232"),NSFontAttributeName:Font()}];
[alert setValue:attr forKey:@"attributedTitle"];
continue;
} //描述颜色
if ([ivarName isEqualToString:@"_attributedMessage"]) {
NSMutableAttributedString *attr = [[NSMutableAttributedString alloc]initWithString:alert.message attributes:@{NSForegroundColorAttributeName:RGB_HEXString(@"#646464"),NSFontAttributeName:Font()}];
[alert setValue:attr forKey:@"attributedMessage"];
continue;
}
}
free(ivars); ivars = class_copyIvarList([UIAlertAction class], &count);
for (int i=; i<count; i++) {
Ivar ivar = ivars[i];
NSString *name = [NSString stringWithCString:ivar_getName(ivar) encoding:NSUTF8StringEncoding];
if ([name isEqualToString:@"_titleTextColor"]) {
[no setValue:RGB_HEXString(@"#323232") forKey:@"titleTextColor"];
[ok setValue:RGB_HEXString(@"#c30d23") forKey:@"titleTextColor"];
}
}
free(ivars); [alert addAction:no];
[alert addAction:ok];
[self presentViewController:alert animated:YES completion:nil];
#endif
@end

3.应用:

 [self.viewModel requestOrderShopList:self.requestModel callback:^(IOAResponse *response) {
dispatch_async(dispatch_get_main_queue(), ^{
[self stopProgress];
NSArray <IOAOrderGroup *> *group = response.responseObject;
if (group) {
if (group.count == && self.requestModel.page_no.integerValue == ) {
self.requestModel.page_no = [NSString stringWithFormat:@"%ld", self.requestModel.page_no.integerValue+];
}
[self.dataArr removeAllObjects];
[self.dataArr addObjectsFromArray:response.responseObject];
[self.tableView reloadData];
if (self.dataArr.count == ) {
//空页面
[self showNoOrderPage:@"目前还没有待付款订单" withImage:@"order"];
return ; }
} else {
if ([response isNoNetwork] && self.dataArr.count == ) {
//无网络
[self showNoNetworkPage];
return;
}
if ([response isRequestServerError]) {
//后台错误
[self showServerErrorPage];
return;
}
}
});
}];

可以直接copy,有一个点要主要

[self showServerErrorPage]这些方法,我是继承了三四层,你可以改成类方法,直接用类调用,这些都是源代码,可以用,这个暂不考虑上传git,谢谢观看

IOS空数据页面,网络加载失败以及重新登陆View的封装(不需要继承)的更多相关文章

  1. 当h5页面图片加载失败后,给定一个默认图

    本文主要讨论页面中图片加载失败后替换默认图片的几种方式 重点来了:一定要记住error事件不冒泡. 相关的知识点:jquery的ready方法.$("img").error().i ...

  2. WebView加载失败或网络异常时,替换WebView的错误界面;

    WebView在加载失败时会显示一个失败原因的界面,各个手机显示的界面还都不一样,部分手机还会把Url显示出来:我们要做的就是统一加载失败的界面: 大概思路:在WebView这个控件上面再覆盖一个Vi ...

  3. SwiftUI - 一步一步教你使用UIViewRepresentable封装网络加载视图(UIActivityIndicatorView)

    概述 网络加载视图,在一个联网的APP上可以讲得上是必须要的组件,在SwiftUI中它并没有提供如 UIKit 中的UIActivityIndicatorView直接提供给我们调用,但是我们可以通过 ...

  4. [IOS]UIWebView 请求网络页面或者加载本地资源页面

    UIWebView是一个能够显示网页的IOS视图控件,我们可以用它来访问一个网站.下面是具体的实例: 操作步骤: 1.首先在xib文件中拖放一个UIWebView控件到view中 2.将下载的页面以及 ...

  5. HBuilder mui 手机app开发 Android手机app开发 ios手机app开发 打开新页面 预加载页面 关闭页面

    创建子页面 在mobile app开发过程中,经常遇到卡头卡尾的页面,此时若使用局部滚动,在android手机上会出现滚动不流畅的问题: mui的解决思路是:将需要滚动的区域通过单独的webview实 ...

  6. iOS网络加载图片缓存策略之ASIDownloadCache缓存优化

    iOS网络加载图片缓存策略之ASIDownloadCache缓存优化   在我们实际工程中,很多情况需要从网络上加载图片,然后将图片在imageview中显示出来,但每次都要从网络上请求,会严重影响用 ...

  7. js/jquery控制页面动态加载数据 滑动滚动条自动加载事件--转他人的

    js/jquery控制页面动态加载数据 滑动滚动条自动加载事件--转他人的 相信很多人都见过瀑布流图片布局,那些图片是动态加载出来的,效果很好,对服务器的压力相对来说也小了很多 有手机的相信都见过这样 ...

  8. HTTP 筛选器 DLL C:\Windows\Microsoft.Net\Framework\v4.0.30319\aspnet_filter.dll 加载失败。数据是错误。

    今天在一台win2003的云主机上,安装.net 4.0时,所有的网站都打不开了.打开事件查看器,发现以下错误: HTTP 筛选器 DLL C:\Windows\Microsoft.Net\Frame ...

  9. 微信页面script标签添加crossorigin=“anonymous”导致页面加载失败

    公司一个微信企业号项目,突然出现页面数据加载失败,页面报错信息如下 意思是前端向服务端发送跨域资源请求访问这个js文件,但是服务端并不同意,所以服务端拒绝访问这个地址. 后来发现将crossorigi ...

随机推荐

  1. Java相关错误

    http://blog.csdn.net/pipisorry/article/details/51291063 使用hadoop jar ./Hw2Part1.jar /hw2/example-inp ...

  2. C++之多态性与虚函数

    面向对象程序设计中的多态性是指向不同的对象发送同一个消息,不同对象对应同一消息产生不同行为.在程序中消息就是调用函数,不同的行为就是指不同的实现方法,即执行不同的函数体.也可以这样说就是实现了&quo ...

  3. (六十四)iOS的socket实现(C+OC混合实现)

    对于微博.微信朋友圈之类的网络通信,使用JSON完全可以满足需求,但是如果要制作网络游戏,就需要建立一个持久连接,这时候就要考虑使用socket. 在iOS上实现socket大体有两种方法,一是借助自 ...

  4. Java 8新特性探究(五)Base64详解

    BASE64 编码是一种常用的字符编码,在很多地方都会用到.但base64不是安全领域下的加密解密算法.能起到安全作用的效果很差,而且很容易破解,他核心作用应该是传输数据的正确性,有些网关或系统只能使 ...

  5. Java应用服务器Resin

    Resin是CAUCHO公司(http://www.caucho.com/)的产品,是一个非常流行的支持servlets 和jsp的引擎,速度非常快.Resin本身包含了一个支持HTTP/1.1的WE ...

  6. 十大常见Java String问题

    翻译人员: 铁锚 翻译时间: 2013年11月7日 原文链接: Top 10 questions of Java Strings 本文介绍Java中关于String最常见的10个问题: 1. 字符串比 ...

  7. ORACLE里锁有以下几种模式,v$locked_object,locked_mode

    ORACLE里锁有以下几种模式: 0:none 1:null 空 2:Row-S 行共享(RS):共享表锁,sub share  3:Row-X 行独占(RX):用于行的修改,sub exclusiv ...

  8. 认识一下Android 事件分发机制

    1.引子 由于android是采用分层布局(可以想象成PS时的图层概念一样),这样才可以在有限大小的手机屏幕上完成一些复杂的操作.当手指点击屏幕开始,这些动作在各层之间如何传递?就引出了Android ...

  9. JavaScript进阶(九)JS实现本地文件上传至阿里云服务器

    JS实现本地文件上传至阿里云服务器 前言 在前面的博客< JavaScript进阶(八)JS实现图片预览并导入服务器功能>(点击查看详情)中,实现了JS将本地图片文件预览并上传至阿里云服务 ...

  10. OpenCV特征点检测算法对比

    识别算法概述: SIFT/SURF基于灰度图, 一.首先建立图像金字塔,形成三维的图像空间,通过Hessian矩阵获取每一层的局部极大值,然后进行在极值点周围26个点进行NMS,从而得到粗略的特征点, ...