UITableView现在边整边总结。

预计分两个部分,第一个部分主要是对UITableView本身属性的学习。第二个部分可能会是加上一个编辑按钮以及对列表的操作。

今天先学习第一部分。


第一部分,我主要通过一个实例来学习:TableView的增量加载。

什么是增量加载?大概就是下拉刷新,上拉加载更多这些功能。在这里我们的数据是本地模拟的数据。服务器数据请求类似。

要实现增量加载,我的做法是数据源得分页(希望有更好做法的朋友能够下方留言交流)

数据源分页,简单说,数据源会有两个属性,pageIndex和pageSize。pageSize是每页的大小,pageIndex是页数。在数据加载的时候,我会首先从数据源取得pageIndex=1的数据,保存在数组array中,然后每次需要增量加载更多的时候,便会去取得pageIndex++的数据,加到array里,然后reloadData;

以上是大概思路,接下来是具体实现:

在这里再复习一下基类和派生类的用法,因为增量加载的TableView会在很多地方用到,你不能每个用到的地方,都去写一次。所以应该抽个基类。

【插一嘴先】:由于我直接截取的代码片段,有些没解释的东西读者能理解就理解,不能理解不影响本文主旨阅读的。

@interface IncrementalTableView : UITableView<UITableViewDelegate,UITableViewDataSource>

新手经常犯的问题,尤其是直接从故事版入手的新童鞋,这里没法连线,所以一定要手动设置TableView的Delegate和DataSource!(哈哈,我在说自己,找了好久才反应过来)

self.delegate = self;
self.dataSource = self;

然后,实现dataSource最主要的三个方法

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
-(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

其中头两个根据需要,进行异常判断和设置,在这里我分别返回的数组个数和1

第三个方法由于本类只是基类,所以就留给派生类们各自去实现了。

嗯,基本的TableView的架子就搭起了,然后只需要派生类的实现自己的时候,传入数据就可以了,类似

[super.mArray addObjectsFromArray:nArray];//mArray就是我定义的数据源,是NSMutableArray类型
[self reloadData];

接下来就是实现增量加载了,(增量加载的方法,我也没有好办法,网上很多demo我看上去很费力,希望有好想法的朋友一样留言交流交流)

增量加载的实现是通过实现UIScrollDelagate,计算拉动的位移来实现的。

我在scrollViewDidScroll方法里,判断拉动的距离,然后在scrollViewDidEndDragging方法里调用加载数据的方法。

- (void)scrollViewDidScroll:(UIScrollView *)sender{
int marggin_Y = [[NSString stringWithFormat:@"%f",sender.contentOffset.y+sender.frame.size.height] intValue];
if ([mArray count] == 0) {
return;
}
if (marggin_Y < updateCriticalLine) {
headerLabel.text = @"释放刷新";
isNeedUpdate = YES;
}else {
headerLabel.text = @"下拉刷新列表";
isNeedUpdate = NO;
}
if (marggin_Y > (cellHeight * pageSize)*pageIndex+160) {
footerLabel.text = @"释放加载";
isNeedLoad = YES;
}else {
footerLabel.text = @"下拉加载更多";
isNeedLoad = NO;
}
}

稍微解释一下,代码里这些数据是根据临界坐标加上了一些缓冲距离的结果,就是说不会刚刚拉到底部就执行加载更多,而会拉过了多少距离再加载,这个值大家可以自定。iOS7在下拉刷新的时候还会存在兼容性问题,会多20个像素(或者说之前的会少20个像素)。所以说没办法又做了一个版本判断……结果为代码中updateCriticalLine

CellHeight是每个Cell的高度,pageSize和pageIndex如前文介绍,不多做解释。

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
{
if (isLoading == YES) return;
if (isNeedUpdate == YES) {
[self updateInfo];
isLoading = YES;
}
if (isNeedLoad == YES) {
[self getMoreInfo];
[footerIndicator startAnimating];
isLoading = YES;
}
}

之所以放到scrollViewDidEndDragging方法里来加载数据,主要是为了方便用户取消,增强一下体验效果。isLoading是一个标志,不能重复发起请求。

跟着代码走,接下来是updateInfo和getMoreInfo两个方法,updateInfo,就是下拉刷新操作。就是重新调用一遍第一次请求。

这两段代码都应该由派生类实现,主要就是获取数据,我就不多说了,注意一下updateInfo是替换数组,getMoreInfo是追加数组就好了,实例代码上面已经贴过了。

到现在为止,tableView的下拉刷新,上拉加载更多就已经基本实现了。

接下来我们继续优化,增量加载一个必不可少的东西,就是表格的Header和Footer。为了不让用户感觉莫名奇妙的数据加载,友好的提示必不可少。

    //Header、Footer设置
[self setContentInset:UIEdgeInsetsMake(-100, 0, -100, 0)];
header = [[UIView alloc]initWithFrame:CGRectMake(0, 0, cellWidth, 100)];
footer = [[UIView alloc]initWithFrame:CGRectMake(0, 0, cellWidth, 100)];
[header setBackgroundColor:[UIColor lightGrayColor]];
[footer setBackgroundColor:[UIColor lightGrayColor]];
//Header、Footer文字信息设置
headerLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, cellWidth, 40)];
[headerLabel setTextAlignment:NSTextAlignmentCenter];
[headerLabel setBackgroundColor:[UIColor clearColor]];
headerLabel.center = header.center;
[header addSubview:headerLabel];
footerLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, cellWidth, 40)];
[footerLabel setTextAlignment:NSTextAlignmentCenter];
[footerLabel setBackgroundColor:[UIColor clearColor]];
footerLabel.center = footer.center;
[footer addSubview:footerLabel];
//Header、Footer活动指示器设置
/**
*刷新(顶部)指示器不需要
headerIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
headerIndicator.center = CGPointMake(header.center.x-100, header.center.y);
[headerIndicator setHidesWhenStopped:YES];
[header addSubview:headerIndicator];
*/
footerIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
footerIndicator.center = CGPointMake(footer.center.x-100, footer.center.y);
[footerIndicator setHidesWhenStopped:YES];
[footer addSubview:footerIndicator];
//初始化Header、Footer设置
self.tableHeaderView = header;
self.tableFooterView = footer;
self.tableHeaderView.hidden = YES;
self.tableFooterView.hidden = YES;
//[headerIndicator stopAnimating];
[footerIndicator stopAnimating];

嗯,我也是用惯了故事版,纯代码用的不多,反正能解决问题就是。如上示代码初始化了一个Header和一个Footer,并且网上加了活动指示器和描述文字(1、当然这个可以做得更完善,2、后来想想更新的指示器改成了类似Android的Toast,感觉效果更好。)并且默认隐藏,以免数据加载失败之后仍然会出现很怪异的两坨不明物。

当然,说到数据加载失败,我们还得加上数据加载失败的异常处理:

我是这样做的,我在派生类中的updateInfo和getMoreInfo两个方法中,做的判断,如果加载失败,则会共同调用基类的实现方法,

其中更新或者第一次(相同逻辑)失败,则会:

    self.separatorStyle = UITableViewCellSeparatorStyleNone;
btnRetry = [UIButton buttonWithType:UIButtonTypeCustom];
[btnRetry setFrame:CGRectMake(0, 0, 100, 50)];
btnRetry.center = self.center;
[btnRetry setTitle:@"重新加载" forState:UIControlStateNormal];
[btnRetry setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
[btnRetry setTitleColor:[UIColor clearColor] forState:UIControlStateHighlighted];
[btnRetry addTarget:self action:@selector(btnRetry:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:btnRetry];

取消分割线,提供重试按钮(重试的实现就是重新调用一边方法)

加载更多失败的提示方式则是Toast一下(Toast这里就不讲了,自定义,不会的网上很多demo)

There there,看上去一个自定义的增量在家tableView貌似大功告成了!其实我们还可以稍微优化一下……

就是我们的上面加的Footer了,试想一下,如果列表数据内容不足填充列表区域,极端点,只有1个Cell,剩下很长的空白会怎么样呢?答案是骚丑骚丑的Footer会跟在Cell后面。(当然,如果你的Footer很美观,你也可以根据你的需要保留,做提示用。)

怎么去掉?去掉的方式无非就是先判断装满没?如果没满,就去掉。怎么判断?我使用的这个方法:

NSArray *visiblePaths = [self indexPathsForVisibleRows];
if ([visiblePaths count] == [mArray count]) self.tableFooterView.hidden = YES;
else self.tableFooterView.hidden = NO;

利用系统api给的indexPathsForVisibleRows方法,得到可见区域的rows,如果数量等于我所有的rows的数量,说明已经显示完了,然后就让他hidden。

如果你还需要他显示完了不能滚动之类的需求,也一并可以在这里操作。

嗯,到这里真正差不多了,一个完全自定义的增量加载TableView新鲜出炉。技术水平有限,欢迎大神斧正。

UITableView个人使用总结【前篇-增量加载】的更多相关文章

  1. 第五篇 Integration Services:增量加载-Deleting Rows

    本篇文章是Integration Services系列的第五篇,详细内容请参考原文. 在上一篇你学习了如何将更新从源传送到目标.你同样学习了使用基于集合的更新优化这项功能.回顾增量加载记住,在SSIS ...

  2. 第四篇 Integration Services:增量加载-Updating Rows

    本篇文章是Integration Services系列的第四篇,详细内容请参考原文. 回顾增量加载记住,在SSIS增量加载有三个使用案例:1.New rows-add rows to the dest ...

  3. 【译】第五篇 Integration Services:增量加载-Deleting Rows

    本篇文章是Integration Services系列的第五篇,详细内容请参考原文. 在上一篇你学习了如何将更新从源传送到目标.你同样学习了使用基于集合的更新优化这项功能.回顾增量加载记住,在SSIS ...

  4. 【译】第四篇 Integration Services:增量加载-Updating Rows

    本篇文章是Integration Services系列的第四篇,详细内容请参考原文. 回顾增量加载记住,在SSIS增量加载有三个使用案例:1.New rows-add rows to the dest ...

  5. 第三篇 Integration Services:增量加载-Adding Rows

    本篇文章是Integration Services系列的第三篇,详细内容请参考原文. 增量加载是什么增量加载仅加载与先前加载差异的.差异包括:->新增的行->更新的行->删除的行通过 ...

  6. 【译】第三篇 Integration Services:增量加载-Adding Rows

    本篇文章是Integration Services系列的第三篇,详细内容请参考原文. 增量加载是什么增量加载仅加载与先前加载差异的.差异包括:->新增的行->更新的行->删除的行通过 ...

  7. 如何每日增量加载数据到Hive分区表

    如何每日增量加载数据到Hive分区表 hadoop hive shell crontab 加载数据 数据加载到Hive分区表(两个分区,日期(20160316)和小时(10))中 每日加载前一天的日志 ...

  8. 【Win10 应用开发】实现数据的增量加载

    今天,老周有小故事讲,国庆期间.有一次老周在某站台上候公交车.老周旁边也站满了人,突然,有一位头发弄得像电线杆的小伙子,不知为何,没有先兆地就大笑起来. 老周先是看了那小伙子一眼,他手上没有拿什么东西 ...

  9. iOS开发UI篇—懒加载

    iOS开发UI篇—懒加载 1.懒加载基本 懒加载——也称为延迟加载,即在需要的时候才加载(效率低,占用内存小).所谓懒加载,写的是其get方法. 注意:如果是懒加载的话则一定要注意先判断是否已经有了, ...

随机推荐

  1. 阶段5 3.微服务项目【学成在线】_day16 Spring Security Oauth2_16-认证接口开发-Api接口定义

    4.3 认证服务 4.3.1 需求分析 认证服务需要实现的功能如下: 1.登录接口 前端post提交账号.密码等,用户身份校验通过,生成令牌,并将令牌存储到redis. 将令牌写入cookie. 2. ...

  2. Qwidget::update

    void QWidget::update ()分析重绘事件激活 1看看手册中这段话 void QWidget::update () [slot] Updates the widget unless u ...

  3. ubuntu18.04安装chromium浏览器

    sudo add-apt-repository ppa:a-v-shkop/chromium sudo apt-get upate sudo apt-get install chromium-brow ...

  4. LODOP在页面让客户选择打印机

    获取打印机列表可以放在onload事件里,如过当前是使用的c-lodop,由于websoket链接需要时间,一进入页面可能会报错,被准备好或网页没下载完成等,也可以在点击事件里让用户获取打印机.之前写 ...

  5. SSRF——漏洞利用(二)

    0x01 概述 上篇讲述了SSRF的一般用法,用http协议来进行内网探测,攻击内网redis,接下来讨论的是SSRF的拓展用法,通过,file,gopher,dict协议对SSRF漏洞进行利用. 0 ...

  6. 26.Spark创建RDD集合

    打开eclipse创建maven项目 pom.xml文件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:x ...

  7. web平台大数据请求传输性能处理

    在XMLHttpRequest请求中使用ArrayBuffer方式,和后端服务器进行二进制的传输交互. 在项目中发现随着用户增长,部分前端功能,请求的数据量越来越大,传统的josn的方式,在下载.序列 ...

  8. Jmeter 跨线程组传递参数 之两种方法(转)

    终于搞定了Jmeter跨线程组之间传递参数,这样就不用每次发送请求B之前,都需要同时发送一下登录接口(因为同一个线程组下的请求是同时发送的),只需要发送一次登录请求,请求B直接用登录请求的参数即可,直 ...

  9. 1204: 移位运算(C)

    一.题目 http://acm.wust.edu.cn/problem.php?id=1204&soj=0 二.分析 无符号短整数关键字为:unsigned short: 无符号短整数长为2字 ...

  10. python2.7 编码问题

    python 2.7编码问题,着实令人头疼不已,这两天抽闲想真正弄明白.需要弄清楚这个问题,首先需要明白ASCII,Unicode 和 UTF-8之间的关系. 进行对上述几种概念进行描述之前,先进行简 ...