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里面当然是用代理了

  1.  
    @protocol LoadingDataViewDelegate <NSObject>
  2.  
     
  3.  
    @required
  4.  
    -(nullable UIView *)loadingDataViewWithNodata:(nullable LoadingDataView *)parent ;
  5.  
    @required
  6.  
    -(nullable UIView *)loadingDataViewWithNoNet:(nullable LoadingDataView *)parent ;
  7.  
    @required
  8.  
    -(nullable UIView *)loadingDataViewWithLoading:(nullable LoadingDataView *)parent ;
  9.  
     
  10.  
    @required
  11.  
    -(nullable NSArray *)loadingDataViewBindArrarys:(nullable LoadingDataView *)parent;
  12.  
     
  13.  
    @end
  14.  
     

话又说回来,视图必须把代理和容器(UITableView 或 UICollectionView)链接起来,而且需要告诉容器一些事件,什么时候开始请求,什么时候结束请求

  1.  
    @interface LoadingDataView : UIView
  2.  
     
  3.  
    -(nullable id)initSrollView:(nullable UIScrollView *)scrollView delegate:(id<LoadingDataViewDelegate>)delegate;
  4.  
     
  5.  
    @property (nonatomic, weak, nullable) id <LoadingDataViewDelegate> delegate;
  6.  
     
  7.  
    -(void)startShowView;
  8.  
    -(void)endShowView:(NSError *)error responese:(id)response;

也就这里暴露了两个方法,开始请求&结束请求

上面我说过,需要子类重写三个界面,正在加载,没有数据,没有网络,而且这个三个界面是互斥的(互斥什么意思自己百度去)

我的做法是将三个View一次加在LoadingView上,然后把LoadingView加在UITableView或UICollectionView上,代码奉上

  1.  
    @implementation LoadingDataView{
  2.  
     
  3.  
     
  4.  
    UIView *noDataView;
  5.  
    UIView *noNetView;
  6.  
    UIView *loadingView;
  7.  
    NSArray *arrList;
  8.  
     
  9.  
     
  10.  
    }
  11.  
     
  12.  
     
  13.  
    -(nullable id)initSrollView:(nullable UIScrollView *)scrollView delegate:(id<LoadingDataViewDelegate>)delegate{
  14.  
     
  15.  
    if (self=[super init]) {
  16.  
    self.delegate=delegate;
  17.  
     
  18.  
     
  19.  
    arrList=[delegate loadingDataViewBindArrarys:self];
  20.  
     
  21.  
    self.frame=CGRectMake(0, 0, scrollView.frame.size.width, scrollView.frame.size.height);
  22.  
     
  23.  
    noDataView=[delegate loadingDataViewWithNodata:self ];
  24.  
    noNetView=[delegate loadingDataViewWithNoNet:self ];
  25.  
    loadingView=[delegate loadingDataViewWithLoading:self ];
  26.  
     
  27.  
    [self addSubview:noDataView];
  28.  
    [self addSubview:noNetView];
  29.  
    [self addSubview:loadingView];
  30.  
     
  31.  
    [self showLoadingView];
  32.  
     
  33.  
     
  34.  
    }
  35.  
     
  36.  
     
  37.  
    [scrollView addSubview:self];
  38.  
     
  39.  
    return self;
  40.  
     
  41.  
     
  42.  
     
  43.  
    }
  44.  
     
  45.  
     
  46.  
    -(void)showLoadingView{
  47.  
    self.hidden=NO;
  48.  
    loadingView.hidden=NO;
  49.  
    noNetView.hidden=YES;
  50.  
    noDataView.hidden=YES;
  51.  
    }
  52.  
     
  53.  
    -(void)showNoNetView{
  54.  
    self.hidden=NO;
  55.  
    loadingView.hidden=YES;
  56.  
    noNetView.hidden=NO;
  57.  
    noDataView.hidden=YES;
  58.  
    }
  59.  
    -(void)showNoDataView{
  60.  
    self.hidden=NO;
  61.  
    loadingView.hidden=YES;
  62.  
    noNetView.hidden=YES;
  63.  
    noDataView.hidden=NO;
  64.  
    }
  65.  
     
  66.  
    -(void)showNormalView{
  67.  
    self.hidden=YES;
  68.  
     
  69.  
    }
  70.  
     
  71.  
    -(void)startShowView{
  72.  
     
  73.  
     
  74.  
    if (arrList.count==0) {
  75.  
    [self showLoadingView];
  76.  
    }else{
  77.  
    [self showNoNetView];
  78.  
    }
  79.  
     
  80.  
    }
  81.  
     
  82.  
    -(void)endShowView:(NSError *)error responese:(id)response{
  83.  
    if (error==nil) {
  84.  
     
  85.  
    if ([arrList count]==0) {
  86.  
    [self showNoDataView];
  87.  
    }else{
  88.  
    [self showNormalView];
  89.  
    }
  90.  
     
  91.  
     
  92.  
    }else{
  93.  
     
  94.  
    if ([arrList count]==0) {
  95.  
    [self showNoNetView];
  96.  
    }else{
  97.  
    [self showNormalView];
  98.  
    }
  99.  
    }
  100.  
     
  101.  
     
  102.  
    }
  103.  
    -(nullable NSArray *)loadingDataViewBindArrarys:(nullable LoadingDataView *)parent{
  104.  
     
  105.  
    return [self.delegate loadingDataViewBindArrarys:parent];
  106.  
     
  107.  
    }
  108.  
     
  109.  
    -(UIView *)nodataView:(LoadingDataView *)parent {
  110.  
     
  111.  
    return [self.delegate loadingDataViewWithNoNet:parent];
  112.  
    }
  113.  
    -(UIView *)nonetView:(LoadingDataView *)parent {
  114.  
     
  115.  
     
  116.  
    return [self.delegate loadingDataViewWithNoNet:parent];
  117.  
    }
  118.  
    -(UIView *)loadingView:(LoadingDataView *)parent {
  119.  
     
  120.  
    return [self.delegate loadingDataViewWithLoading:parent];
  121.  
    }
  122.  
     
  123.  
    @end

现在LoadingView这个类我们已经处理完了, 那么怎么使用了  ?首先,我建议你写一个BaseViewController,每个类都继承这个BaseViewCotroller,当然我只是建议,如果你不这么干,也可以,农夫山泉建议零售价2元,很多小店就不按建议卖。然后像这样

  1.  
    #import <UIKit/UIKit.h>
  2.  
    #import "LoadingDataViewDelegate.h"
  3.  
     
  4.  
    @interface BaseViewController : UIViewController<LoadingDataViewDelegate>
  5.  
     
  6.  
    @end

并重写代理方法

  1.  
    #import "BaseViewController.h"
  2.  
     
  3.  
     
  4.  
     
  5.  
    @interface BaseViewController ()
  6.  
     
  7.  
    @end
  8.  
     
  9.  
    @implementation BaseViewController
  10.  
     
  11.  
    - (void)viewDidLoad {
  12.  
    [super viewDidLoad];
  13.  
    // Do any additional setup after loading the view.
  14.  
     
  15.  
     
  16.  
    }
  17.  
    -(nullable NSArray *)loadingDataViewBindArrarys:(nullable LoadingDataView *)parent{
  18.  
     
  19.  
     
  20.  
    return nil;
  21.  
     
  22.  
    }
  23.  
     
  24.  
     
  25.  
    -(UIView *)loadingDataViewWithNoNet:(LoadingDataView *)parent{
  26.  
     
  27.  
     
  28.  
    UIView *vi=[[UIView alloc] init];
  29.  
    vi.frame=CGRectMake(0, 0, parent.frame.size.width, parent.frame.size.height);
  30.  
    vi.backgroundColor=[UIColor cyanColor];
  31.  
     
  32.  
    return vi;
  33.  
    }
  34.  
     
  35.  
     
  36.  
     
  37.  
    -(UIView *)loadingDataViewWithNodata:(LoadingDataView *)parent{
  38.  
     
  39.  
    UIView *vi=[[UIView alloc] init];
  40.  
    vi.frame=CGRectMake(0, 0, parent.frame.size.width, parent.frame.size.height);
  41.  
    vi.backgroundColor=[UIColor redColor];
  42.  
    return vi;
  43.  
     
  44.  
     
  45.  
    }
  46.  
    -(UIView *)loadingDataViewWithLoading:(LoadingDataView *)parent{
  47.  
     
  48.  
    UIView *vi=[[UIView alloc] init];
  49.  
    vi.frame=CGRectMake(0, 0, parent.frame.size.width, parent.frame.size.height);
  50.  
    vi.backgroundColor=[UIColor yellowColor];
  51.  
    return vi;
  52.  
     
  53.  
    }
  54.  
     
  55.  
     
  56.  
    - (void)didReceiveMemoryWarning {
  57.  
    [super didReceiveMemoryWarning];
  58.  
    // Dispose of any resources that can be recreated.
  59.  
    }

神马意思了。。这就是最基本的没有网络,没有数据,和加载数据的界面,你重写神马样的都可以,如果你的全局三种默认界面都是一样的话,你只需要在这个基类中重写一次就可以。

然后,如何把LoadingView ,数据,和容器关联起来了  ?

我把http请求稍稍封装了下, 如果不熟悉block自己百度。。。

源码如下

  1.  
    @interface TestViewController ()<UITableViewDataSource,UITableViewDelegate>{
  2.  
     
  3.  
    UITableView *table;
  4.  
     
  5.  
    LoadingDataView *loadingView;
  6.  
    NSMutableArray *arrList;
  7.  
     
  8.  
     
  9.  
     
  10.  
    }
  11.  
     
  12.  
    @end
  13.  
     
  14.  
    @implementation TestViewController
  15.  
     
  16.  
    - (void)viewDidLoad {
  17.  
    [super viewDidLoad];
  18.  
     
  19.  
    arrList=[[NSMutableArray alloc] init];
  20.  
    // Do any additional setup after loading the view.
  21.  
    table=[[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
  22.  
    table.delegate=self;
  23.  
    table.dataSource=self;
  24.  
    [self.view addSubview:table];
  25.  
     
  26.  
    loadingView=[[LoadingDataView alloc] initSrollView:table delegate:self];
  27.  
     
  28.  
    [self POST:@"your URL" parameters:nil startBlock:^{
  29.  
    [loadingView startShowView];
  30.  
    } endBlock:^(NSDictionary *response, NSError *error) {
  31.  
    [loadingView endShowView:error responese:response];
  32.  
    }];
  33.  
     
  34.  
    }
  35.  
     
  36.  
     
  37.  
     
  38.  
    -(NSArray *)loadingDataViewBindArrarys:(LoadingDataView *)parent{
  39.  
    return arrList;
  40.  
    }
  41.  
     
  42.  
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
  43.  
     
  44.  
    return [arrList count];
  45.  
    }
  46.  
    -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
  47.  
    return 1;
  48.  
    }
  49.  
    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
  50.  
    return 44;
  51.  
    }
  52.  
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
  53.  
    return [[UITableViewCell alloc] init];
  54.  
    }
  55.  
    -(void)POST:(NSString *)URLString
  56.  
    parameters:(NSDictionary *)dic
  57.  
    startBlock:(void (^ __nullable)(void))startBlock
  58.  
    endBlock:(void (^ __nullable)(NSDictionary *response,NSError * error))endBlock
  59.  
     
  60.  
    {
  61.  
     
  62.  
    startBlock();
  63.  
     
  64.  
     
  65.  
     
  66.  
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
  67.  
     
  68.  
     
  69.  
     
  70.  
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
  71.  
     
  72.  
     
  73.  
    [manager POST:URLString parameters:dic progress:^(NSProgress * _Nonnull uploadProgress) {
  74.  
     
  75.  
     
  76.  
    } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  77.  
     
  78.  
    NSDictionary *obj = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
  79.  
     
  80.  
    endBlock(obj,nil);
  81.  
     
  82.  
     
  83.  
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  84.  
    endBlock(nil,error);
  85.  
     
  86.  
    }];
  87.  
     
  88.  
     
  89.  
     
  90.  
     
  91.  
    }
  92.  
     
  93.  
     
  94.  
     
  95.  
    - (void)didReceiveMemoryWarning {
  96.  
    [super didReceiveMemoryWarning];
  97.  
    // Dispose of any resources that can be recreated.
  98.  
    }

注意:这里的TestViewController 是继承 BaseViewController的

如下:

  1.  
    @interface TestViewController : BaseViewController
  2.  
     
  3.  
    @end

OK ,这就是我的思路。。。

UITableView加载数据,没有数据,没有网络界面处理的更多相关文章

  1. UITableView加载网络数据的优化

    UITableView加载网络数据的优化 效果 源码 https://github.com/YouXianMing/Animations // // TableViewLoadDataControll ...

  2. hive 压缩全解读(hive表存储格式以及外部表直接加载压缩格式数据);HADOOP存储数据压缩方案对比(LZO,gz,ORC)

    数据做压缩和解压缩会增加CPU的开销,但可以最大程度的减少文件所需的磁盘空间和网络I/O的开销,所以最好对那些I/O密集型的作业使用数据压缩,cpu密集型,使用压缩反而会降低性能. 而hive中间结果 ...

  3. HTTP 筛选器 DLL C:\Windows\Microsoft.Net\Framework\v4.0.30319\aspnet_filter.dll 加载失败。数据是错误。

    今天在一台win2003的云主机上,安装.net 4.0时,所有的网站都打不开了.打开事件查看器,发现以下错误: HTTP 筛选器 DLL C:\Windows\Microsoft.Net\Frame ...

  4. [原创.数据可视化系列之三]使用Ol3加载大量点数据

    不管是百度地图还是高德地图,都很难得见到在地图上加载大量点要素,比如同屏1000的,因为这样客户端性能会很低,尤其是IE系列的浏览器,简直是卡的要死.但有的时候,还真的需要,比如,我要加载全球的AQI ...

  5. jsTree 的简单用法--异步加载和刷新数据

    首先这两个文件是必须要引用的,还有就是引用 jQuery 文件就不说了: <link href="/css/plugins/jsTree/style.min.css" rel ...

  6. 使用getJSON()方法异步加载JSON格式数据

    使用getJSON()方法异步加载JSON格式数据 使用getJSON()方法可以通过Ajax异步请求的方式,获取服务器中的数组,并对获取的数据进行解析,显示在页面中,它的调用格式为: jQuery. ...

  7. 异步加载回来的数据不受JS控制了

    写成下面这种方式时,异步加载回来的数据不受JS控制 $(."orderdiv").click(function(){ $(this).find(".orderinfo&q ...

  8. echarts 图表重新加载,原来的数据依然存在图表上

    问题 在做一个全国地图上一些饼图,并且向省一级的地图钻取的时候,原来的饼图依然显示 原因 echars所有添加的图表都在一个series属性集合中,并且同一个echars对象默认是合并之前的数据的,所 ...

  9. mxnet自定义dataloader加载自己的数据

    实际上关于pytorch加载自己的数据之前有写过一篇博客,但是最近接触了mxnet,发现关于这方面的教程很少 如果要加载自己定义的数据的话,看mxnet关于mnist基本上能够推测12 看pytorc ...

随机推荐

  1. sql 重复数据查询

    具体代码: ); ORDER BY tcount DESC;

  2. Git&GitHub

    Git是一个开源的分布式版本控制系统,可以有效.高速地处理从很小到非常大的项目版本管理.  Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软 ...

  3. 浅析data:image/png;base64的应用

    ...我也是加一个网安交流群发现了他们的入群密码是这个 数据:图像/ PNG; BASE64,iVBORw0KGgoAAAANSUhEUgAAANwAAAAoCAIAAAAaOwPZAAAAAXNSR ...

  4. 解决ubuntu下,QQ重启后出现个人文件夹已被占用的问题

    首先,是wine QQ的安转教程:Wine安装最新版QQ(8.9.2)的简单教程 - Powered by Discuz! 里面作者也提到了关于重启后出现个人文件夹被占用的情况. 如下: 这里,如果不 ...

  5. Nmap参考指南(Man Page)

    Table of Contents 描述 译注 选项概要 目标说明 主机发现 端口扫描基础 端口扫描技术 端口说明和扫描顺序 服务和版本探测 操作系统探测 时间和性能 防火墙/IDS躲避和哄骗 输出 ...

  6. 微信小程序接入,https服务器搭建和调试

    在进行小程序开发时候,调试时候,希望在本地搭建一个https环境. 准备条件: 1.公网主机(阿里云或者腾讯云主机) 2外网访问工具natapp 步骤: 1.在主机上安装nginx(nginx转发到n ...

  7. KazaQ's Socks (找规律)

    #include<iostream> using namespace std; #define ll long long ll n, m; ll t; int main(){ while ...

  8. mysql锁2

    死锁: 指两个事务或者多个事务在同一资源上相互占用,并请求对方所占用的资源,从而造成恶性循环的现象. 出现死锁的原因: 系统资源不足: 进程运行推进的顺序不当: 资源分配不当. 产生死锁的四个必要条件 ...

  9. day05 数据基本类型及内置方法:字符串str、列表list

    一:可变不可变类型 1.可变类型 值改变,id不变,说明是直接改变原值,是可变类型 2.不可变类型 值改变,id也跟着改变,说明是产生了新的值,是不可变类型 二:数字类型 1.整型Int 用途: 记录 ...

  10. python日志等级输出删选

    有时候我们会删选一下输出的信息 当做日志进行文件保存 但是我们程序中有可能有自己不想存到日志文件中的输出信息 我们要做一些的删选  然后进行保存 代码如下: #!/usr/bin/python # - ...