一.问题

对于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. Android开发学习之路--NDK、JNI之初体验

    好久没有更新博客了,最近一直在看一个仿微信项目,然后看源码并自己实现下,相信经过这个项目可以让自己了解一个项目中的代码以及种种需要注意的事项.不知不觉中博客已经快要40w访问量,而且排名也即将突破30 ...

  2. Android之Notification-android学习之旅(二)

    notification常用于下拉式的消息推送. Notification的构成 Nitification的实例 1.新建一个Builder,要选Notification.compat包. 2.然后用 ...

  3. 如何自动增加和从代码读取Xcode项目的版本号

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) Xcode项目和版本号相关的有2个地方Version和Buil ...

  4. (NO.00004)iOS实现打砖块游戏(十一):"一闪一闪亮晶晶,我们都是小星星"

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 现在一个基本的游戏逻辑已经搭建好了,但是感觉还是缺点什么呢? 蠢 ...

  5. Cookie 进阶

    Cookie作为一个客户端技术被广泛的应用着.我今天也来谈一谈我对Cookie的理解. 先来一个小菜(实现"上次登录时间") 具体的思路如下: 通过request.getCooki ...

  6. 03 SeekBar 音频播放拖拽进度条

    八,  SeekBar  音频播放拖拽进度条       >                 android:progress="40"   第一进度         and ...

  7. WebLogic11g-负载分发

    负载均衡的实现方式有很多种,这里只介绍三种相对来说成本较低的方案(维护成本以及费用成本)weblogic自带的proxy.apache.nginx  1.weblogic自带的proxy方式:  1) ...

  8. 【一天一道LeetCode】#121. Best Time to Buy and Sell Stock

    # 一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Say ...

  9. Android移动后端服务(BAAS)快速搭建后台服务器之Bmob-android学习之旅(75)

    个人移动开发者的最头疼的问题,就是App的网络后台,包含数据库等,国外目前有比较成熟的解决方案,但是限制于墙的问题,推荐国内的解决方案,比较出名的是Bmob和AVOS cloud和Atom等,这一次我 ...

  10. Java对象引用处理机制

    翻译人员: 铁锚 翻译时间: 2013年11月13日 原文链接: How does Java handle aliasing? 什么是Java的引用别名机制 Java的引用别名机制(原文为Aliasi ...