最近的业务需求要改一个很古老的界面:所有内容都是由frame实现,没有xib,没有autolayout,而且高度是经过手动计算每一个控件的内容加起来返回的,并且根据网络请求的数据会有四种样式,听起来就头大git
硬着头皮把界面改好后看到计算cell高度那里密密麻麻的if else真的下不了手了,想着能不能找到什么第三方能够作,接着想起了FDTemplateLayoutCell,百度出品的很著名的计算autolayout的工具,之前使用过,要大量修改本来的代码结构,把cellForRowAtIndexPath里的逻辑抽取出来太麻烦就没用,想了一下,经过layoutSuview就能拿到正确的cell了,那用这个来计算高度不就行了吗?因而乎就着手写了这个工具github
一开始只是为了尽量简单和尽量不改动原有代码就能拿到高度,后来想一想就算是autolayout,也能够简单用layoutIfNeed拿到正确的cell啊,因而就把autolayout也支持进去了,再后来发现计算frame的方式(须要注册一个最底部的view)能够用在不完整的autolayout,因此无论约束完不完整都支持了swift
大部分的iOS11子版本上更新cell都会有动画问题,甚至当contentOffset不为CGPointZero的时候,tableView reloadData都会致使位置闪一下,只要把estimatedRowHeight设置为0就没有这些问题了,这个真的没办法,就算苹果默认开了这个也只能关了乖乖实现heightForRowAtIndexPath缓存
因此这个工具仍是颇有用的bash
开源地址:github网络
顺便求个星星!谢谢app
#import "UITableView+MDKAutoLayoutHeight.h"
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return [tableView.autoLayoutHeight heightForRowAtIndexPath:indexPath];
}
复制代码
若是须要对高度作什么事情(好比加个间距啊),能够用这个方法从新计算行高框架
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return [tableView.autoLayoutHeight heightForRowAtIndexPath:indexPath cacheKey:acachekey handle:^CGFloat(__kindof UITableViewCell *cell, CGFloat height) {
return height + 20;
}];
}
复制代码
MDKAutoLayoutRegisterHeight
设置哪一个view是最底部的view:#import "UITableView+MDKAutoLayoutHeight.h"
@interface PartOfAutolayoutCell()
@proterty(nonatomic,strong)UIView *bottomView;
@end
@implementation PartOfAutolayoutCell
+(void)initialize{
MDKAutoLayoutRegisterHeight(self, bottomView)
}
@end
复制代码
而且若是实现了这个方法,那这套工具也能适用于用frame布局的cell,只要你是在layoutSubview中布局的(其余方式如放在sizeThatFit之类的应该也能用吧..大概),若是你遇到哪些地方用frame设置cell的控件位置后无效的,请告诉我工具
顺便一提,MDKAutoLayoutRegisterHeight() 是用C语言的宏实现的,若是你是用swift的话,须要用MDKAutoLayoutHeight.(registerHeight:_decisionView:#keyPath(view.bottom)) 填入最底部的view对应的属性名布局
若是你须要缓存cell的高度到内存,只须要在cell中引入 <MDKTableviewCellCacheHeightDelegate>
,实现 -MDKModelHash
方法,返回一个具备惟一性的字符串给我就行,好比:
-(NSString *)MDKModelHash{
return @(_model.ID).description;
}
复制代码
若是是可能改变cell内容的话,能够把ID和决定cell内容是否有变化的标志符传给我,好比:
-(NSString *)MDKModelHash{
return [NSString stringWithFormat:@"%@%@",@(_model.ID),@(_model.isDelete)];
}
复制代码
等等等等.....
pod 'UITableView-MDKAutoLayoutHeight'
复制代码
pod 'UITableView-MDKAutoLayoutHeight/diskCache'
复制代码
当tableview dealloc的时候就会把内存中的缓存写入磁盘 我提供了下面这些方法用来管理磁盘的缓存
import UITableView+MDKAutoLayoutHeightDiskCache.h
- (void)updateDiskCache;//用于某些会一直活着的tableview
- (void)removeCacheFor:(Class)cell;
- (void)removeAllCache;
复制代码
若是你dequeue cell的时候是这样的:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
return [tableView dequeueReusableCellWithIdentifier:@"Identifier" forIndexPath:indexPath];
}
复制代码
app就会crash,由于我是经过这个datasource方法获取cell的,而-dequeueReusableCellWithIdentifier:forIndexPath:
这个方法会调用 table.delegate -heightForRowAtIndexPath
因此就会陷入无限循环......解决办法是不用这个方法,改为-dequeueReusableCellWithIdentifier:
qeueu cell
我实在没有想到必定要用这个方法的理由,若是有遇到什么状况是必定要用这个dequeue cell的话,请告诉我缘由谢谢,我试试看有没有办法避开这个问题
部分用来肯定contentView宽度的代码来自UITableView-FDTemplateLayoutCell