控制器中网络请求+占位图代码块(基础版)

基础版本

  • 导入占位图文件
#import "BSTBitmapView.h"
  • 遵守代理
BSTBitmapViewDelegate
  • 分类属性
@property(nonatomic,assign)NSInteger pageIndex;
@property(nonatomic,assign)NSInteger pageNumber;
@property(nonatomic,strong)BSTBitmapView *bitmapView;
@property(nonatomic,strong)NSMutableArray<<#modelClass#> *> *dataSource;
  • 懒加载
- (BSTBitmapView *)bitmapView
{
    if (!_bitmapView) {
        BSTBitmapView *view = [[BSTBitmapView alloc]initWithFrame:CGRectMake(0, 0, self.mainView.width, self.mainView.height)];
        [self.mainView addSubview:view];
        view.delegate = self;
        _bitmapView = view;
    }
    return _bitmapView;
}
- (NSMutableArray<<#modelClass#>*> *)dataSource
{
    if (!_dataSource) {
        _dataSource = [NSMutableArray array];
    }
    return _dataSource;
}
  • 初始化相关ViewDidLoad和createProperty方法
    1.在createProperty
self.pageIndex = 1;
self.pageNumber = 10;
[self mainView];
self.bitmapView.top = 0;
self.bitmapView.type = BitmapViewTypeLoading;
[self createNetMethod];
  • 网络请求大模块
方法集合
#pragma mark - 网络请求
- (void)createNetMethod
{
    
}
- (void)createRefresh
{
    
}
//下拉刷新
- (void)loadNewData
{
    
}
//上拉加载
- (void)loadMoreData
{
    
}
- (void)loadMyMessage
{
    
}
- (void)endRefresh
{
    
}
- (NSArray *)handleData:(NSObject *)dataModel
{
    return @[];
}
- (void)refreshHeadCode:(NSObject *)dataModel
{
    
}
- (void)refreshFooterCode:(NSObject *)dataModel
{
    
}
#pragma mark - 占位图
- (void)refreshNoDataBitMapView
{
    
}
- (void)refreshNetErrorBitMapView
{
    
}
#pragma mark - BSTBitmapView代理
- (void)bstBitmapView:(BSTBitmapView *)bitmapView backType:(BitmapViewType)type
{
    
}
createNetMethod
[self createRefresh];
WK(weakSelf)
//延迟 不然app直接进来会有网络状态改变
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [PPNetworkHelper networkStatusWithBlock:^(PPNetworkStatusType status) {
        NSLog(@"statusChange:%ld",status);
        if (status == PPNetworkStatusNotReachable) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [weakSelf refreshNetErrorBitMapView];
                [sharedKeyWindow showWarning:kbstTipNetNoConnect];
            });
        } else {
            dispatch_async(dispatch_get_main_queue(), ^{
                //如果没有数据 加载第一页的数据 如果有数据加载下一页
                if (weakSelf.dataSource.count == 0) {
                    [weakSelf loadNewData];
                } else {
                    if (weakSelf.mainView.mj_footer.state != MJRefreshStateNoMoreData && weakSelf.mainView.mj_footer) {
                        [weakSelf loadMoreData];
                    }
                }
            });
        }
    }];
});
createRefresh
self.mainView.mj_header = [MarryGiftHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
[self loadNewData];//静态刷新
//[self.mainView.mj_header beginRefreshing];
loadNewData
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    //恢复可刷新状态
    if (self.mainView.mj_footer) {
        [self.mainView.mj_footer removeFromSuperview];
    }
    [self endRefresh];
    //star
    if ([PPNetworkHelper isNetwork]) {
        self.pageIndex = 1;
        [self loadMyMessage];
    } else {
        [self refreshNetErrorBitMapView];
        [sharedKeyWindow showWarning:kbstTipNetNoConnect];
    }
});
loadMoreData
//[self endRefresh]; 放在这里也挺好的 只显示StateIdle状态了 但是怕停止重新拉 会重复请求 但是测试也没有重复
if ([PPNetworkHelper isNetwork]) {
    self.pageIndex ++;
    [self loadMyMessage];
} else {
    [self endRefresh];
    [sharedKeyWindow showWarning:kbstTipNetError];
}
loadMyMessage
WK(weakSelf)
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
NSMutableDictionary *t = [NSMutableDictionary dictionary];
[parameters setValue:t forKey:@"t"];
[parameters setValue:[NSString stringWithFormat:@"%ld",(long)self.pageNumber] forKey:@"pageSize"];
[parameters setValue:[NSString stringWithFormat:@"%ld",self.pageIndex] forKey:@"pageNum"];
[t setValue:@"0" forKey:@"couponType"];
[t setValue:sharedUserAccount.sellerId forKey:@"scoSellerId"];
[AppNetworkHelper POST:@"app/sysCoupon/getSellerCoupons" parameters:parameters success:^(id responseObject) {
    CouponItemModel *responModel = [CouponItemModel modelWithJSON:responseObject];
    if (responModel.success) {
        if (weakSelf.pageIndex == 1)
        {
            //--------------头部刷新--------------//
            [weakSelf refreshHeadCode:responModel];
            //处理没有数据的占位图
            [weakSelf refreshNoDataBitMapView];
        } else {
            //--------------脚部刷新--------------//
            [weakSelf refreshFooterCode:responModel];
        }
    } else {
        [weakSelf endRefresh];
        [weakSelf refreshNetErrorBitMapView];
        [sharedKeyWindow showWarning:responModel.message];
    }
}];
endRefresh
if (self.mainView.mj_header) {
    [self.mainView.mj_header endRefreshing];
}
if (self.mainView.mj_header) {
    [self.mainView.mj_footer endRefreshing];
}
handleData
return dataModel.data.list;
refreshHeadCode
[self.dataSource removeAllObjects];
[self.dataSource addObjectsFromArray:[self handleData:dataModel]];
//加载头部之类的

//刷新mainView
[self.mainView reloadData];
[self endRefresh];
//添加脚步刷新 会自动销毁替换的
dispatch_async(dispatch_get_main_queue(), ^{
    //1.如果分页数量满额的
    //  1.1 如果contentSize.height 大与自身 则需要加入脚步
    //  1.2 如果contentSize.height 小与自身 则不需要加入脚步 请求下一个接口
    //2.如果分页数量小于满额
    //  2.1  如果contentSize.height 大与自身 则需要加入脚步 提醒没有更多了
    //  2.2  如果contentSize.height 小于自身 则不需要加入脚步
    //3.如果是0
    //  3.1  直接移除脚步 一个cell都没有要脚步干啥
    if (dataModel.data.list.count >= self.pageNumber) {
        if (self.mainView.contentSize.height > self.mainView.height) {
            MJRefreshAutoNormalFooter *footer = [MarryFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)];
            self.mainView.mj_footer = footer;
        } else {
            [self loadMoreData];
        }
    } else if (dataModel.data.list.count > 0){
        if (self.mainView.contentSize.height > self.mainView.height) {
            MJRefreshAutoNormalFooter *footer = [MarryFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)];
            [footer endRefreshingWithNoMoreData];
            self.mainView.mj_footer = footer;
        } else {
            if (self.mainView.mj_footer) {
                [self.mainView.mj_footer removeFromSuperview];
            }
        }
    } else {
        if (self.mainView.mj_footer) {
            [self.mainView.mj_footer removeFromSuperview];
        }
    }
});
refreshFooterCode
[self.dataSource addObjectsFromArray:[self handleData:dataModel]];
if (dataModel.data.list.count > 0) {
    [self.mainView reloadData];
    [self endRefresh];
}
//1.如果分页数量满额的 无需处理
//  1.1 如果contentSize.height 大与自身  无任何操作
//  1.2 如果contentSize.height 小与自身  请求下个接口
//2.如果分页数量小于满额
//  2.1  如果contentSize.height 大与自身  提醒没有更多了
//  2.2  如果contentSize.height 小于自身 则不需要加入脚步
dispatch_async(dispatch_get_main_queue(), ^{
    if (dataModel.data.list.count >= self.pageNumber) {
        if (self.mainView.contentSize.height > self.mainView.height) {
            MJRefreshAutoNormalFooter *footer = [MarryFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)];
                self.mainView.mj_footer = footer;
        } else {
            [self loadMoreData];
        }
    } else {
        if (self.mainView.contentSize.height > self.mainView.height) {
            [self.mainView.mj_footer endRefreshingWithNoMoreData];
        } else {
            if (self.mainView.mj_footer) {
                [self.mainView.mj_footer removeFromSuperview];
            }
        }
    }
});
refreshNoDataBitMapView
//占位图
if (self.dataSource.count == 0) {
    self.bitmapView.type = BitmapViewTypeNoData;
    [self.mainView addSubview:self.bitmapView];
    dispatch_async(dispatch_get_main_queue(), ^{
        self.bitmapView.frame = self.mainView.bounds;
        self.bitmapView.origin = CGPointMake(0, 0);
    });
} else {
    self.bitmapView.type = BitmapViewTypeNormal;
    [self.view insertSubview:self.bitmapView belowSubview:self.mainView];
    dispatch_async(dispatch_get_main_queue(), ^{
         //留着扩大滑动范围用
        self.bitmapView.frame = self.mainView.frame;
    });
}
refreshNetErrorBitMapView
if (self.dataSource.count == 0) {
    if ([PPNetworkHelper isNetwork]) {
        self.bitmapView.type = BitmapViewTypeServerCrash;
    } else {
        self.bitmapView.type = BitmapViewTypeNetError;
    }
    [self.mainView addSubview:self.bitmapView];
    dispatch_async(dispatch_get_main_queue(), ^{
        self.bitmapView.frame = self.mainView.bounds;
        self.bitmapView.origin = CGPointMake(0, 0);
    });
} else {
    self.bitmapView.type = BitmapViewTypeNormal;
    [self.view insertSubview:self.bitmapView belowSubview:self.mainView];
    dispatch_async(dispatch_get_main_queue(), ^{
         //留着扩大滑动范围用
        self.bitmapView.frame = self.mainView.frame;
    });
}
  • 占位图代理方法
if (type == BitmapViewTypeLoading) {
    NSLog(@"加载中....");
} else if (type == BitmapViewTypeNetError || type == BitmapViewTypeServerCrash) {
    NSLog(@"网络错误");
    [self loadNewData];
} else if (type == BitmapViewTypeNoData) {
    NSLog(@"没有数据");
    [self loadNewData];
}
  • 优化地方

  • 扩大滑动范围
    1.必须在主线程 或者延迟几秒


    占位图-完善.png

    2.UICollectionView、UITableView不一样 UICollectionView可以改变Edgeinset的top bottom扩大范围

  • 存在头部 记得减去 头部
  • 爱置换的确认订单 有区头 区尾 所以还是加入到主队列里吧

UITableView加载流程-dispatch_get_main_queue重要性

0.png
1.png
2.png
3.png

总结

  • 改变展位图type和获取UITableView滑动范围和改变滑动范围 应该在主队列中 因为UITableView刷新后才可以添加
  • UITableView可以改变滑动范围、UICollectionView应该不行哦


    dispatch_after_0秒执行顺序.png
dispatch_main.png

你可能感兴趣的:(控制器中网络请求+占位图代码块(基础版))