tableView在开发过程中用到很多,关于cell高度的计算我大致用过3种方式。
一、简单情况
一开始在开发过程中,业务需求很少,渲染tableView时可以在
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
中计算一遍高度,在UITableViewCell中再计算一遍,由于场景简单,代码看起来也还算清晰,只要保证两边一致就可以。
二、稍复杂情况
业务场景渐渐复杂,按照上面的方法两边都根据业务逻辑进行判断和计算高度变的复杂了,特别是如果在cell里修改页面上一个label的字体而改变这个label的高度时,需要同时在Controller文件中的
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
中再同步修改一遍,很烦,所以我们想到在数据源中计算高度,在接口取回数据的时候,对数据进行处理的过程中就根据相应的业务逻辑计算cell的高度,放在数据源DTO中,在渲染tableView的时候不管是在tableView:(UITableView )tableView heightForRowAtIndexPath:(NSIndexPath )indexPath中还是在cell里面,都根据数据源中的计算好的高度来,这样高度的计算就只在一个地方进行,修改也只在一个地方进行。
三、很复杂的情况
业务逻辑越来越复杂,上述第二种方法的弊端就体现出来,在DTO中准备数据计算高度的时候,是根据业务逻辑来的,所以会写很多逻辑判断代码,在cell中绘制视图的时候,也是根据业务逻辑来的,也会写很多业务逻辑判断代码。这两边的代码有很多是相似的,而且由于业务非常复杂,这些代码就会很多,看起来很难看。
这种情况下,我们就只在cell绘制里写业务逻辑,绘制视图,不同的是在cell中增加一个属性kHeight,代表当前绘制视图的底的位置,每绘制完一个视图相应的更新kHeight,最后绘制完了kHeight就是该cell的高度。但是这时候有个问题,tableView在reload的时候是会先走到tableView:(UITableView )tableView heightForRowAtIndexPath:(NSIndexPath )indexPath的,这里的高度怎么算呢?我们在Controller里提供一个cell,然后用这个cell去调用cell的绘制视图代码,但这不是目的,目的是从中获取到绘制完的cell的高度。这个cell重复利用,调用方式和tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath )indexPath中cell的调用方式一样,只是调用完并不会真的绘制视图,而是获取了cell高度。
这样,我们高度的计算就只在cell中存在,各种复杂的业务逻辑判断代码也只在cell里存在。