1. 程式人生 > >iOS學習之-Cell動態高度計算

iOS學習之-Cell動態高度計算

標籤(空格分隔): 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的文章: