iOS之UITableView如何优雅的插入数据: 旋转180°下拉加载cell顶置

姓名:唐来宾  学号:17101223417

转载http://mp.weixin.qq.com/s/J0DKug2QSIaMguMTEkSrXQ

【嵌牛导读】一般项目里面用到UITableView的概率还是灰常大的, 我的项目从一开始也用了. 大概的来说就是类似一个收件箱的功能, 推送来一条消息就加一个cell, 这是很简单的.

【嵌牛鼻子】数据插入,旋转

【嵌牛提问】如何简化数据插入过程?

【嵌牛正文】一. 概述

一般项目里面用到UITableView的概率还是灰常大的, 我的项目从一开始也用了. 大概的来说就是类似一个收件箱的功能, 推送来一条消息就加一个cell, 这是很简单的. 蓝鹅, 接下来经历了两次需求更改:

1. 增加'数据本地化'的功能;

2. 增加查看历史消息功能, 也就是下拉加载更多的消息.

第一个还好说, 就是用FMDB弄了个简单的数据库, 差不多就是获取数据的途径变成从数据库获取而已;

在增加了第一个需求之后, 叠加提出第二个需求, 看起来也很简单哦, 不就是加数据嘛. 但是, 当我开始做起来的时候才发现, 坑蛮多的.

这篇文章是基于我自己项目所写的, 可能在一些地方处理比较特殊并不具备"普世价值"; 但从开发者学习的角度来说, 我始终认为思路比代码重要. 所以这里我可能在思路方面比较啰嗦点, 直接要代码的慎重选择啊.

先说一下, 需求二里面主要遇到的坑有两个:

坑一 : 下拉加载的10条消息, 显示直接在第0-4条, 要看第5-9条的话又得反方向上滑

为了解决坑一, 将tableview和cell都旋转了180°, 这时候, 坑二来了

坑二 : 在初始cell数量较少的时候, 推送新消息过来增加cell的时候导致界面跳动

二. 项目过程

2.1需求分析

由于第一个需求太过简单, 所以就忽略啦. 这里直接讲第二个需求的.

刚刚上面讲的不是很清楚, 这里补充一下第二个需求的具体:

1.进入到界面的时候, 里面要先显示最多10条消息;

2.下拉可以加载历史数据(每次10条);

3.当有新消息推送过来的时候, 要添加在最底部, 并滚动到最底部;

4.三日内做完.

刚看到这个需求的时候, 我的第一个反应是这太TM简单了, too simple! 看老夫如何在三天时间以内用半天做完再用两天半假装没做(tou)完(lan).

2.2 坑一

蓝鹅, 忙活半天过后, 我发现自己too young too naive????. 这就是上面说的坑一, 图是这样的, 可以看到点击"消息+1"的时候还算正常, 但是下拉加载更多消息(10条)的时候, 都是停留在最顶部, 也就是上面坑一说的, 要看第5-9条的时候, 得反方向上滑

正常的.gif

为了解决坑一, 我尝试过调试NSIndexPath并且使用scrollToRowAtIndexPath:<#(nonnull nsindexpath=""> atScrollPosition:<#(uitableviewscrollposition)#> animated:<#(bool)#>]方法来各种折腾....再过了半天之后????放弃了, 下班, 对, 下班!!!谁说程序猿都得加班的.

2.3 坑二

昨晚想了一(yi)下(晚)和简单的实践(说好的不加班呢, 变相加班????!), 发现在uitableview的底部使用inset...和scroll...方法拼接数据很完美, 脑洞大开," 独创"(后来发现网上也有)ios大法之乾坤大挪移----将整个tableview旋转180°!!!!! 当然cell也要旋转180°.

旋转的代码分别是:

CGAffineTransform transform =CGAffineTransformMakeRotation(M_PI);

[tbV setTransform:transform];

cell的旋转:

CGAffineTransform transform =CGAffineTransformMakeRotation(M_PI);

[self.contentView setTransform:transform];

当然, 使用mjrefresh的话, 就得用原来使用的mj_header换成mj_footer了(关于mjrefresh的使用).

弄好之后是这样的, cell直接在最底部:

倒过来一.gif

这明显是不行的, 为了使得cell数量比较少的时候可以顶置(实际是底置, 因为tableview旋转了180°了), 于是想到了根据tableView.contentSize.height(关于 tableView.contentSize你想了解的)来设置tableView.contentInset, 代码是这样的

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{

if (tableView.contentSize.height < tableView.frame.size.height)

{

tableView.contentInset = UIEdgeInsetsMake(tableView.frame.size.height - tableView.contentSize.height - RSRealValue(120), 0, 0, 0);

}

}

运行出来一看, 哇, 完美解决!!!! 蓝鹅, 高兴地太早了. 这时候下拉加载时没问题的, 但新加一条消息的时候, 新的cell会把原来的cell顶上去, 而不是拼接在最下面, 如图:

倒过来contentInset.gif

经过一番思考, 本人大致的认为, 在新加入cell的时候, 原来的tableView.contentSize还是没变, 也就是说tableView.contentSize的布局其实还是只到了上一个cell的底部, 并以此往复, 所以出现了上图里面加了3条新消息再下滑的时候才出现.

这时候, 又想到了一个方法, 可以尝试监听tableView.contentSize还动态修改tableView.contentSize.....&%$#@!@#$%&%$过程省略几百字, 直接说结果吧, 然并卵. 而且, 在ios的UITableView里面, 并不是很推荐修改tableView.contentSize, 因为这个是苹果自身维持动态平衡的, 我们强心修改的话会影响其平衡, 而且在控制台会出现警报. 所以很不推荐.

就这样又折腾了半天.....下午整个人都在想这个问题. 终于在吃了一颗糖果之后, 想到一个方法:

为啥不通过记录cell的总高度来代替tableView.contentSize, 然后设置一个透明的tableheaderview来代替设置tableView.contentInset快被自己的机智感动了.

这样既可以绕过上面说的问题了. 说干就干.

需要在cell的model文件里面增加一个记录本cell高度的属性:

// 计算出来的cell的高度

@property (nonatomic, assign) CGFloat cellHeight;

同时, 也得在控制器文件里面增加一个记录所有cell总高度的属性:

// cell的叠加高度

@property (nonatomic, assign) CGFloat cellsTotalHeight;

并且写了它的懒加载方法, 这样每次在获取总高度的时候都能保证是最新的

- (CGFloat)cellsTotalHeight{

CGFloat heightAll = 0;

for (int i = 0; i < self.dataMulArr.count; i ++) {

OneModel *model = self.dataMulArr[i];

heightAll = heightAll + model.cellHeight;

}

_cellsTotalHeight = heightAll;

NSLog(@"cell总高度: %f",heightAll);

return heightAll;

}

同时, 返回头部视图和高度是这样de(为了方便调试, 先把头部视图设置成有个半透明色)

#pragma mark- 返回头部视图

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{

UIView *headV = [[UIView alloc] init];

//    headV.backgroundColor = [UIColor clearColor];

headV.backgroundColor = RSColorFromRGBA(0x00FF00, 0.5);

return headV;

}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{

NSLog(@"头部视图高度中cell: %f", self.cellsTotalHeight);

CGFloat headHeight = 0;

if (self.cellsTotalHeight < self.tbV.frame.size.height)

{

headHeight = self.tbV.frame.size.height - self.cellsTotalHeight - RSRealValue(240);

}

return headHeight;

}

跑出来是这样的:

倒过来加header.gif

这时候再把tableheaderview的背景色改成透明的, 就成了这样了:

倒过来加header透明.gif

果然完美解决了, 这时候其实只剩一天时间假装没完(偷)成(lan)了.

不过还是要注意一下, 看图倒过来加header.gif将tableheaderview改成透明之后, 新增cell还是会被tableheaderview挡住, 所以最后一个cell是点击不到的. 因为我项目里面的cell不需要点击, 所以这个问题我可以忽略; 如果小伙伴项目里面的cell需要点击的话, 就要将tableheaderview高度进一步减去新增cell的高度哦. 这里我就不做具体代码了, 小伙伴们自己探索一下把.

三. 小总结

总结起来, 这里面几个关键点是:

1.旋转180°

2.不使用reloaddata方法, 而是使用inser....和scroll...两个方法

3.通过增加tableheaderview来实现倒转tableview之后cell的顶置, 并且动态的改变tableheaderview的高度.

这个虽然只是项目的一小部分, 但每次解决问题之后都能获得成就感, 这就是码农单纯的快乐吧.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容