Template auto layout cell for automatically UITableViewCell height calculating

Overview

UITableView-FDTemplateLayoutCell

Overview

Template auto layout cell for automatically UITableViewCell height calculating.

Demo Overview

Basic usage

If you have a self-satisfied cell, then all you have to do is:

#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];
    }];
}

Height Caching API

Since iOS8, -tableView:heightForRowAtIndexPath: will be called more times than we expect, we can feel these extra calculations when scrolling. So we provide another API with cache by index path:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return [tableView fd_heightForCellWithIdentifier:@"identifer" cacheByIndexPath:indexPath configuration:^(id cell) {
        // configurations
    }];
}

Or, if your entity has an unique identifier, use cache by key API:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
	Entity *entity = self.entities[indexPath.row];
    return [tableView fd_heightForCellWithIdentifier:@"identifer" cacheByKey:entity.uid configuration:^(id cell) {
        // configurations
    }];
}

Frame layout mode

FDTemplateLayoutCell offers 2 modes for asking cell's height.

  1. Auto layout mode using "-systemLayoutSizeFittingSize:"
  2. Frame layout mode using "-sizeThatFits:"

Generally, no need to care about modes, it will automatically choose a proper mode by whether you have set auto layout constrants on cell's content view. If you want to enforce frame layout mode, enable this property in your cell's configuration block:

cell.fd_enforceFrameLayout = YES;

And if you're using frame layout mode, you must override -sizeThatFits: in your customized cell and return content view's height (separator excluded)

- (CGSize)sizeThatFits:(CGSize)size {
    return CGSizeMake(size.width, A+B+C+D+E+....);
}

Debug log

Debug log helps to debug or inspect what is this "FDTemplateLayoutCell" extention doing, turning on to print logs when "calculating", "precaching" or "hitting cache".Default to "NO", log by "NSLog".

self.tableView.fd_debugLogEnabled = YES;

It will print like this:

** FDTemplateLayoutCell ** layout cell created - FDFeedCell
** FDTemplateLayoutCell ** calculate - [0:0] 233.5
** FDTemplateLayoutCell ** calculate - [0:1] 155.5
** FDTemplateLayoutCell ** calculate - [0:2] 258
** FDTemplateLayoutCell ** calculate - [0:3] 284
** FDTemplateLayoutCell ** precached - [0:3] 284
** FDTemplateLayoutCell ** calculate - [0:4] 278.5
** FDTemplateLayoutCell ** precached - [0:4] 278.5
** FDTemplateLayoutCell ** hit cache - [0:3] 284
** FDTemplateLayoutCell ** hit cache - [0:4] 278.5
** FDTemplateLayoutCell ** hit cache - [0:5] 156
** FDTemplateLayoutCell ** hit cache - [0:6] 165

About self-satisfied cell

a fully self-satisfied cell is constrainted by auto layout and each edge("top", "left", "bottom", "right") has at least one layout constraint against it. It's the same concept introduced as "self-sizing cell" in iOS8 using auto layout.

A bad one :( - missing right and bottom non-self-satisfied

A good one :)
self-satisfied

Notes

A template layout cell is created by -dequeueReusableCellWithIdentifier: method, it means that you MUST have registered this cell reuse identifier by one of:

  • A prototype cell of UITableView in storyboard.
  • Use -registerNib:forCellReuseIdentifier:
  • Use -registerClass:forCellReuseIdentifier:

如果你在天朝

可以看这篇中文博客: http://blog.sunnyxx.com/2015/05/17/cell-height-calculation/

Installation

Latest version: 1.6

pod search UITableView+FDTemplateLayoutCell 

If you cannot search out the latest version, try:

pod setup

Release Notes

We recommend to use the latest release in cocoapods.

  • 1.6 fix bug in iOS 10

  • 1.4
    Refactor, add "cacheByKey" mode, bug fixed

  • 1.3
    Frame layout mode, handle cell's accessory view/type

  • 1.2
    Precache and auto cache invalidation

  • 1.1
    Height cache

  • 1.0
    Basic automatically height calculation

License

MIT

Comments
  • ios10正式版不能计算出正确高度

    ios10正式版不能计算出正确高度

    在iOS10上计算高度调用 fd_heightForCellWithIdentifier:(NSString *)identifier configuration:(void (^)(id cell))configuration 方法时,获取到的contentViewWidth是1000,导致不能正确计算高度了

    opened by jessedog 56
  • 在cell的updateConstraints更新高度约束,有冲突,求指导

    在cell的updateConstraints更新高度约束,有冲突,求指导

    用Masonry写的约束,想动态改变cell内imageView的高度,实现cell的自适应高度。代码如下

    - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
    {
        self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
        if (self) {
            self.imageV = [[UIImageView alloc] init];
            [self.contentView addSubview:self.imageV];
            self.imageV.backgroundColor = [UIColor redColor];
            [self.imageV mas_makeConstraints:^(MASConstraintMaker *make) {
                make.left.top.right.equalTo(self.contentView);
                make.height.equalTo(@(60));
                make.bottom.equalTo(self.contentView).offset(-20);
            }];
        }
        return self;
    }
    
    - (void)updateConstraints
    {
            [self.imageV mas_updateConstraints:^(MASConstraintMaker *make) {
                if (self.indexPath.row % 2 == 0) {
                    make.height.equalTo(@(60));
                } else {
                    make.height.equalTo(@(10));
                }
            }];
    
        [super updateConstraints];
    }
    

    把updateConstraints注释掉,一切都正常,打开updateConstraints动态改变imageView高度时界面效果是达到预期了也能正常运行,但是出现约束冲突提示:

    (
        "<MASLayoutConstraint:0x7f8ab2d6c3a0 UIImageView:0x7f8ab2d6b1c0.top == UITableViewCellContentView:0x7f8ab2d6aaa0.top>",
        "<MASLayoutConstraint:0x7f8ab2d6c730 UIImageView:0x7f8ab2d6b1c0.height == 60>",
        "<MASLayoutConstraint:0x7f8ab2d6c8b0 UIImageView:0x7f8ab2d6b1c0.bottom == UITableViewCellContentView:0x7f8ab2d6aaa0.bottom - 20>",
        "<NSLayoutConstraint:0x7f8ab2d6cf70 UITableViewCellContentView:0x7f8ab2d6aaa0.height == 30>"
    )
    
    Will attempt to recover by breaking constraint 
    <MASLayoutConstraint:0x7f8ab2d6c730 UIImageView:0x7f8ab2d6b1c0.height == 60>
    

    这个跟高度缓存有关吗? 还是我写的约束有问题?求指导

    enhancement 
    opened by ssjk4 30
  • 代码奔溃了

    代码奔溃了

    *** Assertion failure in -[UITableView fd_templateCellForReuseIdentifier:], /Users/cyq/Documents/git/CarPrice/CarPrice/Pods/UITableView+FDTemplateLayoutCell/Classes/UITableView+FDTemplateLayoutCell.m:41

    • Hook 1 (expr -- @import UIKit)
    • Hook 2 (target stop-hook disable) 2016-01-28 14:42:11.093 CarPrice[6288:2450021] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Cell must be registered to table view for identifier - TableSampleIdentifier'

    加了[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"TableSampleIdentifier"];

    opened by cyqluowang 19
  • ios10.2之后处理label自动换行时候会崩溃

    ios10.2之后处理label自动换行时候会崩溃

    • (CGFloat)fd_systemFittingHeightForConfiguratedCell:(UITableViewCell *)cell 方法里的 fittingHeight = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;这行在调用系统方法时候会被UIkit断言阻隔。导致崩溃
    opened by stone54240 17
  • 10.3下报 约束冲突,所有cell都有这种情况

    10.3下报 约束冲突,所有cell都有这种情况

    demo 有会出现这种情况

    cell. UITableViewCellContentView.width = 0 与 cell. UITableViewCellContentView.width = 375 (对应的最大宽度) MAXWidth 冲突

    ** FDTemplateLayoutCell ** layout cell created - FDFeedCell 2017-04-05 15:14:53.986190+0800 Demo[4230:1055755] [LayoutConstraints] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. ( "<NSLayoutConstraint:0x174085eb0 UITableViewCellContentView:0x100422b60.width == 341 (active)>", "<NSLayoutConstraint:0x17008f5a0 'UIView-Encapsulated-Layout-Width' UITableViewCellContentView:0x100422b60.width == 0 (active)>" )

    opened by anyuhao 13
  • 导致sd_webImageView加载图片失败

    导致sd_webImageView加载图片失败

    发现了一个非常极端的BUG 当使用了FD,并且设置了 tableView.estimatedRowHeight ,会导致sd_web有些图片加载不出来,需要滑动列表才会显示出来。 比如我的情况,tableView的head 高度150, cell 高度 280,第二个cell正好处于显示半个的情况,那么第二个cell的图片100%不加载。其他cell的图片也存在不规则的不加载。 如果不设置tableView.estimatedRowHeight 则不会触发这个BUG,不使用FD也不会触发,不知道FD和SD的算法产生了什么冲突。

    opened by FutureChen 10
  • 终于发现作者为什么不更新了。我猜是这个原因。(希望懂的人指导指导一下)

    终于发现作者为什么不更新了。我猜是这个原因。(希望懂的人指导指导一下)

    最近在做项目的时候,一个UITableViewCell的.xib 的autolayout布局,就一个label。上下左右到contentView的上下左右。然后这个库还是在计算高度的时候出现约束冲突,虽然程序没有崩了,看着输出的约束,心里老难受了。然后就各种想办法解决。后来发现自己的app已经是最低版本是8.0(这个和老大商量过得,现在8.0下面的应用应该很少了,我买的那个4s都换了,估计用的人也很少很少了 吧)。我用的self.tableView.estimatedRowHeight = 44; self.tableView.rowHeight = UITableViewAutomaticDimension;发现程序的高度布局一点问题都没有。

    或许这就是作者不在更新这个库的原因吧。不知道我的想法对不对,我的列表数据很少很简单,复杂的布局不知道是什么效果,慢慢再测试吧!希望懂的人指导指导一下。

    opened by binfy 9
  • 动态修改约束的高度,有报错,求指导

    动态修改约束的高度,有报错,求指导

    52b74947-3918-46bd-b93e-0557cd0dc3bc 我这样添加了一个View和约束,并且先设定了蓝色的视图的,高度 而后在代码里修改了蓝色视图的高度

    • (void)configureCell:(UITableViewCell )cell atIndexPath:(NSIndexPath *)indexPath { MMDiaryCell *virtualCell=(MMDiaryCell)cell; // CGFloat raH= arc4random() % 200+20; [virtualCell setMyheight:250]; }

    cell.m里面 -(void)setMyheight:(CGFloat )height { _blueHeigthLayout.constant=height; }

    然后提示了一个约束警告

    2015-12-02 22:29:00.589 MeiMei[1105:33286] Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) ( "<NSLayoutConstraint:0x7f9a3250b940 UIView:0x7f9a325764a0.height == 54>", "<NSLayoutConstraint:0x7f9a32566d60 UIView:0x7f9a325764a0.top == UITableViewCellContentView:0x7f9a32582d90.top + 8>", "<NSLayoutConstraint:0x7f9a3256eeb0 UITableViewCellContentView:0x7f9a32582d90.bottom == UIView:0x7f9a325764a0.bottom + 8>", "<NSLayoutConstraint:0x7f9a32574900 UITableViewCellContentView:0x7f9a32582d90.height == 266>" )

    Will attempt to recover by breaking constraint <NSLayoutConstraint:0x7f9a3250b940 UIView:0x7f9a325764a0.height == 54>

    Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

    是我这样用法存在问题么?

    opened by FutureChen 9
  • How to use without storyboard?

    How to use without storyboard?

    I am using xibs in my project. I followed your guidelines. But, still I am not able to make it work with xib.

    Please provide the details, for how to add it with xib.

    opened by sahil263 9
  • it doesn't work when content contains dynamic image view

    it doesn't work when content contains dynamic image view

    I have one image view inside cell content that loads photo from server. image view content mode is aspect fill and only width has been defined using autolayout in storyboard. height should be increased dynamically based on loaded photo size. constraints for cell content view has been already self-satisfied. what am I missing?

    opened by caofei10119 9
  • 崩溃在

    崩溃在

    • (void)fd_insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation { if (self.fd_autoCacheInvalidationEnabled) { [indexPaths enumerateObjectsUsingBlock:^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) { NSMutableArray *rows = self.fd_cellHeightCache.sections[indexPath.section]; [rows insertObject:@(_FDTemplateLayoutCellHeightCacheAbsentValue) atIndex:indexPath.row]; }]; } [self fd_insertRowsAtIndexPaths:indexPaths withRowAnimation:animation]; // Primary call [self fd_precacheIfNeeded]; }
    opened by AugustRush 9
  • Feature request - add a possibility to customize template cell creatation

    Feature request - add a possibility to customize template cell creatation

    From your readme:

    A template layout cell is created by -dequeueReusableCellWithIdentifier: method, it means that you MUST have registered this cell reuse identifier by one of: A prototype cell of UITableView in storyboard. Use -registerNib:forCellReuseIdentifier: Use -registerClass:forCellReuseIdentifier:

    Usually it is also possible to call dequeueReusableCellWithIdentifier and create a cell in the same place if necessary but you forbid that

    opened by gerchicov-bp 0
  • 各位注意了deleteSections一次删除多个会导致缓存错乱

    各位注意了deleteSections一次删除多个会导致缓存错乱

    因为IndexSet是按从小到大分布,FD枚举删除的时候没考虑到这个问题(其实和 Issue #54 是同一个bug) 解决方案是不应该用枚举的方式逐个删除,而应使用 removeObjectsAtIndexes直接一步删除

    由于FD已经不再维护,所以我们要么整个项目clone下来改,要么只能使用Swizzle替换方法。

    我选的后者,这里给出部分swift代码

    @objc private func _deleteSections(_ sections: IndexSet, with animation: UITableView.RowAnimation) {
            guard fd_indexPathHeightCache.automaticallyInvalidateEnabled, !sections.isEmpty else {
                _deleteSections(sections, with: animation)
                return
            }
            
            // FD框架有严重bug,我们自己来
            let portrait = fd_indexPathHeightCache.value(forKey: "_heightsBySectionForPortrait") as? NSMutableArray
            let landscape = fd_indexPathHeightCache.value(forKey: "_heightsBySectionForLandscape") as? NSMutableArray
            
            portrait?.removeObjects(at: sections)
            landscape?.removeObjects(at: sections)
            
            // 我们已经处理好了,避免FD的bug代码二次处理
            fd_indexPathHeightCache.automaticallyInvalidateEnabled = false
            defer {
                fd_indexPathHeightCache.automaticallyInvalidateEnabled = true
            }
            _deleteSections(sections, with: animation)
        }
    
    opened by cddjr 0
  • Archive

    Archive

    cache the height to model, may is anythings you want

        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: cellIdForMessage(msg:array[safe: indexPath.row]), for: indexPath)
            
            if let model = array[safe: indexPath.row] {
                cell.reloadData(data: model as Any)
                if (model.cellHeigth > CGFloat(0)) == false {
                    let size = cell.contentView.systemLayoutSizeFitting(CGSize(width: YYScreenSize().width, height: 0), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel)
                    model.cellHeigth = size.height
                }
            }
    
            return cell;
        }
    
    opened by grand-china 1
  • FD库能异步计算高度吗

    FD库能异步计算高度吗

    遇到问题: 1.接口请求数据回来,tableView去reload的数据会有明显卡顿。 2.股票行情类app,ws订阅会大量的数据在异步处理完后,会有大量的回调到主线程渲染UI,造成主线程拥塞,FD渲染高度计算不全,一般小于实际高度,经常导致部分cell高度小于实际高度。

    需求: 1.能支持异步计算高度。 2.当接口数据请求回来,可以用FD异步处理好高度,再回调到主线程reload TableView。

    opened by iCoobin 1
Owner
Staying like a fool, forking like a dog.
null
Auto Layout made easy with the Custom Layout.

Auto Layout made easy with the Custom Layout. Getting started CocoaPods CocoaPods is a dependency manager for Cocoa projects. You can install it with

Malith Nadeeshan 1 Jan 16, 2022
Simple Catalyst example (Mac idiom) of a grid-based app populated with photos, with dynamic cell layout switching

Catalyst Photo Grid Simple Catalyst example (Mac idiom) of a grid-based app populated with photos that can animate its cells between two different lay

Steven Troughton-Smith 56 Nov 14, 2022
Fast Swift Views layouting without auto layout. No magic, pure code, full control and blazing fast. Concise syntax, intuitive, readable & chainable. [iOS/macOS/tvOS/CALayer]

Extremely Fast views layouting without auto layout. No magic, pure code, full control and blazing fast. Concise syntax, intuitive, readable & chainabl

layoutBox 2.1k Dec 22, 2022
A declarative Auto Layout DSL for Swift :iphone::triangular_ruler:

Cartography ?? ?? Using Cartography, you can set up your Auto Layout constraints in declarative code and without any stringly typing! In short, it all

Robb Böhnke 7.3k Jan 4, 2023
Auto Layout made easy

EasyPeasy is a Swift framework that lets you create Auto Layout constraints programmatically without headaches and never ending boilerplate code. Besi

Carlos Vidal 1.9k Dec 23, 2022
Lightweight Swift framework for Apple's Auto-Layout

I am glad to share with you a lightweight Swift framework for Apple's Auto-Layout. It helps you write readable and compact UI code using simple API. A

null 349 Dec 20, 2022
An Impressive Auto Layout DSL for iOS, tvOS & OSX. & It is written in pure swift.

KVConstraintKit KVConstraintKit is a DSL to make easy & impressive Auto Layout constraints on iOS, tvOS & OSX with Swift Installation Using CocoaPods

Keshav Vishwkarma 90 Sep 1, 2022
A compact but full-featured Auto Layout DSL for Swift

Mortar allows you to create Auto Layout constraints using concise, simple code statements. Use this: view1.m_right |=| view2.m_left - 12.0 Instead of:

Jason Fieldman 83 Jan 29, 2022
The ultimate API for iOS & OS X Auto Layout — impressively simple, immensely powerful. Objective-C and Swift compatible.

The ultimate API for iOS & OS X Auto Layout — impressively simple, immensely powerful. PureLayout extends UIView/NSView, NSArray, and NSLayoutConstrai

PureLayout 7.6k Jan 6, 2023
Auto Layout In Swift Made Easy

Swiftstraints Swiftstraints can turn verbose auto-layout code: let constraint = NSLayoutConstraint(item: blueView, attr

null 119 Jan 29, 2022
TinyConstraints is the syntactic sugar that makes Auto Layout sweeter for human use.

TinyConstraints is the syntactic sugar that makes Auto Layout sweeter for human use. Features Pure Swift 5 sweetness. Everything you can do with Auto

Robert-Hein Hooijmans 3.8k Jan 5, 2023
Intuitive and powerful Auto Layout library

Align introduces a better alternative to Auto Layout anchors. Semantic. Align APIs focus on your goals, not the math behind Auto Layout constraints. P

Alexander Grebenyuk 338 Oct 18, 2022
⚓️ Declarative, extensible, powerful Auto Layout

EasyAnchor ❤️ Support my apps ❤️ Push Hero - pure Swift native macOS application to test push notifications PastePal - Pasteboard, note and shortcut m

Khoa 449 Nov 10, 2022
Harness the power of AutoLayout NSLayoutConstraints with a simplified, chainable and expressive syntax. Supports iOS and OSX Auto Layout

Masonry Masonry is still actively maintained, we are committed to fixing bugs and merging good quality PRs from the wider community. However if you're

null 18k Jan 5, 2023
Yet Another Swift Auto Layout DSL

FormationLayout Documentation FormationLayout is the top level layout class for one root view. FormationLayout takes a UIView as its rootView. transla

Evan Liu 53 Mar 31, 2022
Lightweight declarative auto-layout framework for Swift

SwiftyLayout SwiftyLayout is a framework that allows to describe layout constraints (ie NSLayoutConstraint) as a simple mathematical formula in a Swif

Hisakuni Fujimoto 15 Nov 7, 2017
Minimal Auto Layout in Swift

Restraint Restraint is a very very small library to help make your use of NSLayoutConstraint in Swift more legible & declarative. Like programmatic vi

The Puffin Supply Project 80 Aug 23, 2022
Swift microframework for declaring Auto Layout constraints functionally

Relayout Relayout is a Swift microframework to make using Auto Layout easier with static and dynamic layouts. Why? If you want to build a UI using App

Steve Streza 560 Nov 19, 2022
Concise Auto Layout API to chain programmatic constraints while easily updating existing constraints.

Concise API for Auto Layout. SnapLayout extends UIView and NSView to deliver a list of APIs to improve readability while also shortening constraint co

Satinder Singh 11 Dec 17, 2021