https://blog.csdn.net/chmod_r_755/article/details/53231461
俗话说的好,傻逼的APP都是相似的,牛逼的APP各有各的牛逼。。。但是UITableView的这个三种状态的默认界面不知道困扰了多少人。。
github上有一个哥们写了一个牛逼的框架:https://github.com/dzenbot/DZNEmptyDataSet,但是本人发现本人不太牛逼,无法驾驭这个牛逼的框架。。 所以本人自己琢磨了一套出来了。。 先上效果图吧 。。
这是一张正常的列表,有数据显示正常的
接下来我们显示几张不正常的,数据正在请求
接下来我们显示几张不正常的,没有网络
接下来我们显示几张不正常的,没有数据
看到这里了你大概猜到我写这篇微博的中心思想了,本人不喜欢扯神马设计模式神马MVC模式,听到某些傻逼的面试官问MVC的时候,我不得不吐槽一把,面试官先生你怎么理解MVC设计模式了 ?
我的设计思路是 使用OC中的代理,也就是Java里面的面向接口编程,扯远了。。。
首先,我的这个LoadingView很明显是加在UITableView或UICollectionView上面的,也就是,在UITableView或UICollectionView上加入了一层View,也就是LoadingView
但是,问题来了, 现在有三个View,第一个是 数据正在加载的时候的View,第二个是没有网络的View, 第三个是没有数据的View, 三个View应该是互斥的,并且三个View都跟数据源有关系, 也就是加入列表中有数据的话,三个View是不显示的。。。而且这三个View最好是让子类重写,别问我问什么,碰到某些变态的设计师,收藏界面A一种View,收藏B一种View,你懂得。。 而且这些视图显示还跟数据有关系,所以必须设置视图代理和数据代理让子类重写
那么我们必须提供一种让子类重写的方法,OC里面当然是用代理了
-
@protocol LoadingDataViewDelegate <NSObject>
-
-
@required
-
-( nullable UIView *)loadingDataViewWithNodata:(nullable LoadingDataView *)parent ;
-
@required
-
-( nullable UIView *)loadingDataViewWithNoNet:(nullable LoadingDataView *)parent ;
-
@required
-
-( nullable UIView *)loadingDataViewWithLoading:(nullable LoadingDataView *)parent ;
-
-
@required
-
-( nullable NSArray *)loadingDataViewBindArrarys:(nullable LoadingDataView *)parent;
-
-
@end
-
话又说回来,视图必须把代理和容器(UITableView 或 UICollectionView)链接起来,而且需要告诉容器一些事件,什么时候开始请求,什么时候结束请求
-
@interface LoadingDataView : UIView
-
-
-( nullable id)initSrollView:(nullable UIScrollView *)scrollView delegate:(id<LoadingDataViewDelegate>)delegate;
-
-
@property (nonatomic, weak, nullable) id <LoadingDataViewDelegate> delegate;
-
-
-( void)startShowView;
-
-( void)endShowView:(NSError *)error responese:(id)response;
也就这里暴露了两个方法,开始请求&结束请求
上面我说过,需要子类重写三个界面,正在加载,没有数据,没有网络,而且这个三个界面是互斥的(互斥什么意思自己百度去)
我的做法是将三个View一次加在LoadingView上,然后把LoadingView加在UITableView或UICollectionView上,代码奉上
-
@implementation LoadingDataView{
-
-
-
UIView *noDataView;
-
UIView *noNetView;
-
UIView *loadingView;
-
NSArray *arrList;
-
-
-
}
-
-
-
-( nullable id)initSrollView:(nullable UIScrollView *)scrollView delegate:(id<LoadingDataViewDelegate>)delegate{
-
-
if (self=[super init]) {
-
self.delegate=delegate;
-
-
-
arrList=[delegate loadingDataViewBindArrarys: self];
-
-
self.frame=CGRectMake(0, 0, scrollView.frame.size.width, scrollView.frame.size.height);
-
-
noDataView=[delegate loadingDataViewWithNodata: self ];
-
noNetView=[delegate loadingDataViewWithNoNet: self ];
-
loadingView=[delegate loadingDataViewWithLoading: self ];
-
-
[ self addSubview:noDataView];
-
[ self addSubview:noNetView];
-
[ self addSubview:loadingView];
-
-
[ self showLoadingView];
-
-
-
}
-
-
-
[scrollView addSubview: self];
-
-
return self;
-
-
-
-
}
-
-
-
-( void)showLoadingView{
-
self.hidden=NO;
-
loadingView.hidden= NO;
-
noNetView.hidden= YES;
-
noDataView.hidden= YES;
-
}
-
-
-( void)showNoNetView{
-
self.hidden=NO;
-
loadingView.hidden= YES;
-
noNetView.hidden= NO;
-
noDataView.hidden= YES;
-
}
-
-( void)showNoDataView{
-
self.hidden=NO;
-
loadingView.hidden= YES;
-
noNetView.hidden= YES;
-
noDataView.hidden= NO;
-
}
-
-
-( void)showNormalView{
-
self.hidden=YES;
-
-
}
-
-
-( void)startShowView{
-
-
-
if (arrList.count==0) {
-
[ self showLoadingView];
-
} else{
-
[ self showNoNetView];
-
}
-
-
}
-
-
-( void)endShowView:(NSError *)error responese:(id)response{
-
if (error==nil) {
-
-
if ([arrList count]==0) {
-
[ self showNoDataView];
-
} else{
-
[ self showNormalView];
-
}
-
-
-
} else{
-
-
if ([arrList count]==0) {
-
[ self showNoNetView];
-
} else{
-
[ self showNormalView];
-
}
-
}
-
-
-
}
-
-( nullable NSArray *)loadingDataViewBindArrarys:(nullable LoadingDataView *)parent{
-
-
return [self.delegate loadingDataViewBindArrarys:parent];
-
-
}
-
-
-( UIView *)nodataView:(LoadingDataView *)parent {
-
-
return [self.delegate loadingDataViewWithNoNet:parent];
-
}
-
-( UIView *)nonetView:(LoadingDataView *)parent {
-
-
-
return [self.delegate loadingDataViewWithNoNet:parent];
-
}
-
-( UIView *)loadingView:(LoadingDataView *)parent {
-
-
return [self.delegate loadingDataViewWithLoading:parent];
-
}
-
-
@end
现在LoadingView这个类我们已经处理完了, 那么怎么使用了 ?首先,我建议你写一个BaseViewController,每个类都继承这个BaseViewCotroller,当然我只是建议,如果你不这么干,也可以,农夫山泉建议零售价2元,很多小店就不按建议卖。然后像这样
-
-
-
-
@interface BaseViewController : UIViewController<LoadingDataViewDelegate>
-
-
@end
并重写代理方法
-
-
-
-
-
@interface BaseViewController ()
-
-
@end
-
-
@implementation BaseViewController
-
-
- ( void)viewDidLoad {
-
[ super viewDidLoad];
-
// Do any additional setup after loading the view.
-
-
-
}
-
-( nullable NSArray *)loadingDataViewBindArrarys:(nullable LoadingDataView *)parent{
-
-
-
return nil;
-
-
}
-
-
-
-( UIView *)loadingDataViewWithNoNet:(LoadingDataView *)parent{
-
-
-
UIView *vi=[[UIView alloc] init];
-
vi.frame= CGRectMake(0, 0, parent.frame.size.width, parent.frame.size.height);
-
vi.backgroundColor=[ UIColor cyanColor];
-
-
return vi;
-
}
-
-
-
-
-( UIView *)loadingDataViewWithNodata:(LoadingDataView *)parent{
-
-
UIView *vi=[[UIView alloc] init];
-
vi.frame= CGRectMake(0, 0, parent.frame.size.width, parent.frame.size.height);
-
vi.backgroundColor=[ UIColor redColor];
-
return vi;
-
-
-
}
-
-( UIView *)loadingDataViewWithLoading:(LoadingDataView *)parent{
-
-
UIView *vi=[[UIView alloc] init];
-
vi.frame= CGRectMake(0, 0, parent.frame.size.width, parent.frame.size.height);
-
vi.backgroundColor=[ UIColor yellowColor];
-
return vi;
-
-
}
-
-
-
- ( void)didReceiveMemoryWarning {
-
[ super didReceiveMemoryWarning];
-
// Dispose of any resources that can be recreated.
-
}
神马意思了。。这就是最基本的没有网络,没有数据,和加载数据的界面,你重写神马样的都可以,如果你的全局三种默认界面都是一样的话,你只需要在这个基类中重写一次就可以。
然后,如何把LoadingView ,数据,和容器关联起来了 ?
我把http请求稍稍封装了下, 如果不熟悉block自己百度。。。
源码如下
-
@interface TestViewController ()<UITableViewDataSource,UITableViewDelegate>{
-
-
UITableView *table;
-
-
LoadingDataView *loadingView;
-
NSMutableArray *arrList;
-
-
-
-
}
-
-
@end
-
-
@implementation TestViewController
-
-
- ( void)viewDidLoad {
-
[ super viewDidLoad];
-
-
arrList=[[ NSMutableArray alloc] init];
-
// Do any additional setup after loading the view.
-
table=[[ UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
-
table.delegate= self;
-
table.dataSource= self;
-
[ self.view addSubview:table];
-
-
loadingView=[[LoadingDataView alloc] initSrollView:table delegate: self];
-
-
[ self POST:@"your URL" parameters:nil startBlock:^{
-
[loadingView startShowView];
-
} endBlock:^( NSDictionary *response, NSError *error) {
-
[loadingView endShowView:error responese:response];
-
}];
-
-
}
-
-
-
-
-( NSArray *)loadingDataViewBindArrarys:(LoadingDataView *)parent{
-
return arrList;
-
}
-
-
-( NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
-
-
return [arrList count];
-
}
-
-( NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
-
return 1;
-
}
-
-( CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
-
return 44;
-
}
-
-( UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
-
return [[UITableViewCell alloc] init];
-
}
-
-( void)POST:(NSString *)URLString
-
parameters:( NSDictionary *)dic
-
startBlock:( void (^ __nullable)(void))startBlock
-
endBlock:( void (^ __nullable)(NSDictionary *response,NSError * error))endBlock
-
-
{
-
-
startBlock();
-
-
-
-
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
-
-
-
-
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
-
-
-
[manager POST:URLString parameters:dic progress:^( NSProgress * _Nonnull uploadProgress) {
-
-
-
} success:^( NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
-
-
NSDictionary *obj = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
-
-
endBlock(obj, nil);
-
-
-
} failure:^( NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
-
endBlock( nil,error);
-
-
}];
-
-
-
-
-
}
-
-
-
-
- ( void)didReceiveMemoryWarning {
-
[ super didReceiveMemoryWarning];
-
// Dispose of any resources that can be recreated.
-
}
注意:这里的TestViewController 是继承 BaseViewController的
如下:
-
@interface TestViewController : BaseViewController
-
-
@end
OK ,这就是我的思路。。。