最近的業務需求要改一個很古老的界面:所有內容都是由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