iOS学习之-Cell动态高度计算

来源:互联网 发布:ip显示是上海阿里云 编辑:程序博客网 时间:2024/05/12 17:52

标签(空格分隔): UITableCell iOS


最近看到一个开源库用来动态计算UITableCell高度的,感觉挺不错,学习下它的实现方式。
UITableView-FDTemplateLayoutCell

这个库的使用很简单,官方文档已经说明了,主要支持两种方式的使用:

  • 简单使用,没有缓存计算过的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的文章:

iOS 8 Tutorial Series: Auto Sizing Table Cells
Auto Layout for Table View Cells with Dynamic Heights

0 0
原创粉丝点击