UITableView加载数据,没有数据,没有网络界面处理
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元,很多小店就不按建议卖。然后像这样
- #import <UIKit/UIKit.h>
- #import "LoadingDataViewDelegate.h"
- @interface BaseViewController : UIViewController<LoadingDataViewDelegate>
- @end
并重写代理方法
- #import "BaseViewController.h"
- @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 ,这就是我的思路。。。
UITableView加载数据,没有数据,没有网络界面处理的更多相关文章
- UITableView加载网络数据的优化
UITableView加载网络数据的优化 效果 源码 https://github.com/YouXianMing/Animations // // TableViewLoadDataControll ...
- hive 压缩全解读(hive表存储格式以及外部表直接加载压缩格式数据);HADOOP存储数据压缩方案对比(LZO,gz,ORC)
数据做压缩和解压缩会增加CPU的开销,但可以最大程度的减少文件所需的磁盘空间和网络I/O的开销,所以最好对那些I/O密集型的作业使用数据压缩,cpu密集型,使用压缩反而会降低性能. 而hive中间结果 ...
- HTTP 筛选器 DLL C:\Windows\Microsoft.Net\Framework\v4.0.30319\aspnet_filter.dll 加载失败。数据是错误。
今天在一台win2003的云主机上,安装.net 4.0时,所有的网站都打不开了.打开事件查看器,发现以下错误: HTTP 筛选器 DLL C:\Windows\Microsoft.Net\Frame ...
- [原创.数据可视化系列之三]使用Ol3加载大量点数据
不管是百度地图还是高德地图,都很难得见到在地图上加载大量点要素,比如同屏1000的,因为这样客户端性能会很低,尤其是IE系列的浏览器,简直是卡的要死.但有的时候,还真的需要,比如,我要加载全球的AQI ...
- jsTree 的简单用法--异步加载和刷新数据
首先这两个文件是必须要引用的,还有就是引用 jQuery 文件就不说了: <link href="/css/plugins/jsTree/style.min.css" rel ...
- 使用getJSON()方法异步加载JSON格式数据
使用getJSON()方法异步加载JSON格式数据 使用getJSON()方法可以通过Ajax异步请求的方式,获取服务器中的数组,并对获取的数据进行解析,显示在页面中,它的调用格式为: jQuery. ...
- 异步加载回来的数据不受JS控制了
写成下面这种方式时,异步加载回来的数据不受JS控制 $(."orderdiv").click(function(){ $(this).find(".orderinfo&q ...
- echarts 图表重新加载,原来的数据依然存在图表上
问题 在做一个全国地图上一些饼图,并且向省一级的地图钻取的时候,原来的饼图依然显示 原因 echars所有添加的图表都在一个series属性集合中,并且同一个echars对象默认是合并之前的数据的,所 ...
- mxnet自定义dataloader加载自己的数据
实际上关于pytorch加载自己的数据之前有写过一篇博客,但是最近接触了mxnet,发现关于这方面的教程很少 如果要加载自己定义的数据的话,看mxnet关于mnist基本上能够推测12 看pytorc ...
随机推荐
- 转:EditPuls 5.0 注册码
EditPlus5.0注册码 注册名 Vovan 注册码 3AG46-JJ48E-CEACC-8E6EW-ECUAW EditPlus3.x注册码 EditPlus注册码生成器链接 http://ww ...
- Linux进程调度策略的发展和演变--Linux进程的管理与调度(十六)
1 前言 1.1 进程调度 内存中保存了对每个进程的唯一描述, 并通过若干结构与其他进程连接起来. 调度器面对的情形就是这样, 其任务是在程序之间共享CPU时间, 创造并行执行的错觉, 该任务分为两个 ...
- AI学习---回归和聚类算法
其他 资料链接:https://pan.baidu.com/s/1ofN2QFxpzC-OtmTFE2fHfw 提取码:o4c2
- Java循环语句怎么用?经典排序算法见真知
Java中循环语句的使用,莫过于在排序算法中使用得最为经典. 排序算法非常的多,不过大体可以分为两种: 一种是比较排序,主要有:冒泡排序,选择排序,插入排序,归并排序,堆排序,快速排序等. 另一种是非 ...
- ASP.NET -- WebForm -- 页面生命周期事件
ASP.NET -- WebForm -- 页面生命周期事件在页生命周期的每个阶段中,页将引发可运行您自己的代码进行处理的事件. 1. PreInit: 使用该事件来执行下列操作: 检查 IsPos ...
- 4.7Python数据处理篇之Matplotlib系列(七)---matplotlib原理分析
目录 目录 前言 (一)总框架分析 (二)函数式的绘图 1.说明: 2.函数绘图的缺优点 3.绘图类的函数 4.操作类的函数 5.例子: (三)面向对象式的绘图 1.基本概念 2.基本对象 3.面向对 ...
- Linux 小知识翻译 - 「SCP和SFTP」
这次想说说「SCP和SFTP」. 不管SCP还是SFTP,都是SSH的功能之一.都是使用SSH协议来传输文件的. 不用说文件内容,就是登录时的用户信息都是经过SSH加密后才传输的,所以说SCP和SFT ...
- 合并两个有序数组的golang实现
给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组. 说明: 初始化 nums1 和 nums2 的元素数量分别为 m 和 n. ...
- 基于python的Selenium使用小结
之前介绍过基于Unittest和TestNG自动化测试框架,然而基于Web端的测试的基础框架是需要Selenium做主要支撑的,这里边给大家介绍下Web测试核心之基于Python的Selenium 一 ...
- Spring Boot 菜鸟教程 application.properties 常用配置
SPRING CONFIG (ConfigFileApplicationListener) spring.config.name 配置文件名称,默认为application spring.config ...