• 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,谢谢观看
  • 相关阅读:
    objectiveC中的序列化(serialize)与反序列化(deserialize)
    objectiveC 的代码文件组织
    [转载]Multicast Explained in Flash 10.1 P2P
    几种异步操作方式
    objectiveC 的内存管理之自动释放池(autorelease pool)
    用VS2010调试微软开放的部分源码
    浏览器窗口尺寸改变时的图片自动重新定位
    数据结构C#版笔记啥夫曼树(Huffman Tree)与啥夫曼编码(Huffman Encoding)
    objectiveC 的内存管理之实例分析
    objectiveC 的OOP(上)类定义、继承及方法调用
  • 原文地址:https://www.cnblogs.com/guohai-stronger/p/8985699.html
Copyright © 2020-2023  润新知