MDKAutoLayoutHeight 自动化UITableviewCell高度计算工具

写这个工具的原因

最近的业务需求要改一个很古老的界面:所有内容都是由frame实现,没有xib,没有autolayout,而且高度是经过手动计算每一个控件的内容加起来返回的,并且根据网络请求的数据会有四种样式,听起来就头大git

硬着头皮把界面改好后看到计算cell高度那里密密麻麻的if else真的下不了手了,想着能不能找到什么第三方能够作,接着想起了FDTemplateLayoutCell,百度出品的很著名的计算autolayout的工具,之前使用过,要大量修改本来的代码结构,把cellForRowAtIndexPath里的逻辑抽取出来太麻烦就没用,想了一下,经过layoutSuview就能拿到正确的cell了,那用这个来计算高度不就行了吗?因而乎就着手写了这个工具github

一开始只是为了尽量简单和尽量不改动原有代码就能拿到高度,后来想一想就算是autolayout,也能够简单用layoutIfNeed拿到正确的cell啊,因而就把autolayout也支持进去了,再后来发现计算frame的方式(须要注册一个最底部的view)能够用在不完整的autolayout,因此无论约束完不完整都支持了swift


另外也会有人问了,iOS11之后UITableView都默认开启estimatedRowHeight了,为何还要手动计算高度呢?

答案固然是由于很差用啊

大部分的iOS11子版本上更新cell都会有动画问题,甚至当contentOffset不为CGPointZero的时候,tableView reloadData都会致使位置闪一下,只要把estimatedRowHeight设置为0就没有这些问题了,这个真的没办法,就算苹果默认开了这个也只能关了乖乖实现heightForRowAtIndexPath缓存

因此这个工具仍是颇有用的bash


功能

  • 高性能: 尽量少的计算cell的高度,而且提供内存和磁盘缓存.
  • 自动更新: 基于数据模型hash的更新,当数据源或者tableview宽度有变化时会自动更新缓存.
  • 内存管理: 当系统提示内存不够的时候自动清理内存缓存.
  • 低侵入性: 基本上不须要改动任何代码结构就能使用这个框架,不像FDTemplateLayoutCell要根据他们的设计改动大量原有代码(还很差用).
  • 轻量级: 这个库的核心组件只有一个文件,一个类和一个tableview分类.
  • 容易使用: 只须要一行代码就能享受彻底自动化的高度计算.

开源地址: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;
	}];
}

复制代码

若是你cell不是彻底填充contentView的约束,你能够用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对应的属性名布局

在内存中缓存高度

若是在heightForRow方法中的acachekey返回nil或者@“”,你须要按照下面的内容手动返回一个cachekey

若是你须要缓存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

相关文章
相关标签/搜索