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,謝謝觀看

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM