基础版本
- 导入占位图文件
#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