iOS學習之-Cell動態高度計算
阿新 • • 發佈:2019-01-23
標籤(空格分隔): UITableCell iOS
這個庫的使用很簡單,官方文件已經說明了,主要支援兩種方式的使用:
- 簡單使用,沒有快取計算過的cell高度
#import "UITableView+FDTemplateLayoutCell.h"
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [tableView fd_heightForCellWithIdentifier:@"reuse identifer" configuration:^(id cell) {
// Configure this cell with data, same as what you've done in "-tableView:cellForRowAtIndexPath:"
// Like:
// cell.entity = self.feedEntities[indexPath.row];
}];
}
- 高階使用,支援快取已經計算過的Cell高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [tableView fd_heightForCellWithIdentifier:@"identifer" cacheByIndexPath:indexPath configuration:^(id cell) {
// configurations
}];
}
並且不用擔心重複使用cell造成高度快取錯誤問題,因為在實現程式碼裡,作者利用OC的執行時 Method Swizzling機制替換了原有的方法,這裡會存在一個問題就是如果使用這個庫,修改了Private method不知道Apo Store稽核會通過不。
UISectionRowData refreshWithSection:tableView:tableViewRowData
這個是私有的當reload Data 或者相關的方法被呼叫時,iOS內部呼叫的方法。該作者替換了這個方法,使得呼叫這個方法之前,會先清空cached 的高度資訊,因此才不用擔心快取高度的問題。具體實現過程如下:
__attribute__((constructor)) static void FDTemplateLayoutCellHeightCacheInvalidationEntryPoint()
{
// Swizzle a private method in a private class "UISectionRowData", we try to assemble this
// selector instead of using the whole literal string, which may be more safer when submit
// to App Store.
NSString *privateSelectorString = [@"refreshWithSection:" stringByAppendingString:@"tableView:tableViewRowData:"];
SEL originalSelector = NSSelectorFromString(privateSelectorString);
Method originalMethod = class_getInstanceMethod(NSClassFromString(@"UISectionRowData"), originalSelector); // 獲取原始例項方法
if (!originalMethod) {
return;
}
void (*originalIMP)(id, SEL, NSUInteger, id, id) = (typeof(originalIMP))method_getImplementation(originalMethod); //通過原始method獲得它的實現
void (^swizzledBlock)(id, NSUInteger, id, id) = ^(id self, NSUInteger section, UITableView *tableView, id rowData) {
// Invalidate height caches first
[tableView fd_invalidateHeightCaches];
// Call original implementation
originalIMP(self, originalSelector, section, tableView, rowData);
};
method_setImplementation(originalMethod, imp_implementationWithBlock(swizzledBlock));
}
裡面的attribute((section(“name”)) 是GCC提供的一種擴充套件,可以自定義段,這裡的這個方法呼叫會在main()函式之前,以及所有classes 被對映到runtime中才執行。
這個擴充套件方法實現主要用到了如下兩個方法:
[NSLayoutConstraint constraintWithItem:cell.contentView attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:CGRectGetWidth(self.frame)];
[cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]
這個方法的使用用來計算適配layout之後,cell的高度,這樣即可動態得到cell的高度。確實很不錯
其他討論cell的文章: