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

标签(空格分隔): 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值