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

相關文章
相關標籤/搜索