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

一.问题

对于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(-5);
        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(10);
        make.left.greaterThanOrEqualTo(self);
        make.right.lessThanOrEqualTo(self);
        make.height.equalTo(@30);
    }];
    
    [self.subTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.titleLabel);
        make.top.equalTo(self.titleLabel.mas_bottom).offset(10);
        make.left.greaterThanOrEqualTo(self);
        make.right.lessThanOrEqualTo(self);
        make.height.equalTo(@25);
    }];
    
    [self.refreshButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(self.subTitleLabel);
        make.top.equalTo(self.subTitleLabel.mas_bottom).offset(10);
//        make.left.greaterThanOrEqualTo(self);
//        make.right.lessThanOrEqualTo(self);
        make.height.equalTo(@30);
        make.width.equalTo(@100);
    }];
}

#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:18];
        _titleLabel.textAlignment = NSTextAlignmentCenter;
    }
    
    return _titleLabel;
}

- (UILabel *)subTitleLabel {
    if (!_subTitleLabel)  {
        _subTitleLabel = [UILabel new];
        _subTitleLabel.textColor = RGB_HEXString(@"#323232");
        _subTitleLabel.font = [UIFont systemFontOfSize:16];
        _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:16];
        [_refreshButton addTarget:self action:@selector(clickedRefreshButton:) forControlEvents:UIControlEventTouchUpInside];
        _refreshButton.layer.cornerRadius = 6;
        _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 = 0;
    CGFloat bottomOffset = 0;
    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 = 0;
    CGFloat bottomOffset = 0;
    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 > 1 && 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 = 0;
Ivar *ivars = class_copyIvarList([UIAlertController class], &count);
for(int i = 0; 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(14)}];
        [alert setValue:attr forKey:@"attributedTitle"];
        continue;
    }
    
    //描述颜色
    if ([ivarName isEqualToString:@"_attributedMessage"]) {
        NSMutableAttributedString *attr = [[NSMutableAttributedString alloc]initWithString:alert.message attributes:@{NSForegroundColorAttributeName:RGB_HEXString(@"#646464"),NSFontAttributeName:Font(14)}];
        [alert setValue:attr forKey:@"attributedMessage"];
        continue;
    }
}
free(ivars);

ivars = class_copyIvarList([UIAlertAction class], &count);
for (int i=0; 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 == 0 && self.requestModel.page_no.integerValue == 0) {
                    self.requestModel.page_no = [NSString stringWithFormat:@"%ld", self.requestModel.page_no.integerValue+1];
                }
                [self.dataArr removeAllObjects];
                [self.dataArr addObjectsFromArray:response.responseObject];
                [self.tableView reloadData];
                if (self.dataArr.count == 0) {
//空页面
                    [self showNoOrderPage:@"目前还没有待付款订单" withImage:@"order"];
                    return ;

                }
            }
            
            else {
                if ([response isNoNetwork] && self.dataArr.count == 0) {
//无网络
                    [self showNoNetworkPage];
                    return;
                }
                if ([response isRequestServerError]) {
//后台错误
                    [self showServerErrorPage];
                    return;
                }
            }
        });
    }];

 

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

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

 

posted @ 2018-05-03 16:57  国孩  阅读(1731)  评论(0编辑  收藏  举报