Iphone - 当每个单元格高度是动态的时,何时计算 tableview 的 heightForRowAtIndexPath? [英] Iphone - when to calculate heightForRowAtIndexPath for a tableview when each cell height is dynamic?

查看:23
本文介绍了Iphone - 当每个单元格高度是动态的时,何时计算 tableview 的 heightForRowAtIndexPath?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经多次看到这个问题,但令人震惊的是,我没有看到一致的答案,所以我自己试试:

I have seen this question asked many times but astoundingly, I have not seen a consistent answer, so I will give it a try myself:

如果您有一个包含您自己的自定义 UITableViewCells 的 tableview,其中包含必须在运行时确定高度的 UITextViews 和 UILabels,您应该如何确定 heightForRowAtIndexPath 中每一行的高度?

If you have a tableview containing your own custom UITableViewCells that contain UITextViews and UILabels whose height must be determined at runtime, how are you supposed to determine the height for each row in heightForRowAtIndexPath?

最明显的第一个想法是通过计算然后求和cellForRowAtIndexPath内单元格内每个视图的高度来计算每个单元格的高度,并存储最终的总高度以供以后检索.

The most obvious first idea is to calculate the height for each cell by calculating and then summing the heights of each view inside the cell inside of cellForRowAtIndexPath, and store that final total height for later retrieval.

但是这不会起作用,因为 cellForRowAtIndexPath 是在 heightForRowAtIndexPath 之后调用的.

This will not work however because cellForRowAtIndexPath is called AFTER heightForRowAtIndexPath.

我唯一能想到的就是在 viewDidLoad 中进行所有计算,然后创建所有 UITableViewCells,计算单元格高度并将其存储在 UITableViewCell 子类中的自定义字段中,然后将每个单元格放入 NSMutableDictionary 中indexPath 作为键,然后简单地使用 cellForRowAtIndexPath 和 heightForRowAtIndexPath 中的 indexPath 从字典中检索单元格,返回自定义高度值或单元格对象本身.

The only thing I can think of is to do all the calculations inside viewDidLoad, create all the UITableViewCells then, calculate the cells height and store that in a custom field inside your UITableViewCell subclass, and put each cell in an NSMutableDictionary with the indexPath as the the key, and then simply retrieve the cell from the dictionary using the indexPath inside cellForRowAtIndexPath and heightForRowAtIndexPath, returning either the custom height value or the cell object itself.

尽管这种方法似乎是错误的,因为它没有使用 dequeueReusableCellWithIdentifier,而是我将一次将所有单元格加载到我的控制器中的字典中,而委托方法只会从字典.

This approach seems wrong though because it does not make use of dequeueReusableCellWithIdentifier, instead I would be loading all the cells at once into a dictionary in my controller, and the delegate methods would be doing nothing more than retrieving the correct cell from the dictionary.

我没有看到任何其他方法可以做到这一点.这是一个坏主意 - 如果是这样,那么正确的方法是什么?

I don't see any other way to do it though. Is this a bad idea - if so, what is the correct way to do this?

推荐答案

Apple 实现 UITableView 的方式对每个人来说并不直观,很容易误解 heightForRowAtIndexPath: 的作用.总体意图是,这是一种更快且内存较少的方法,可以非常频繁地为表中的每一行调用.这与 cellForRowAtIndexPath: 形成对比,后者通常速度较慢且占用更多内存,但仅针对在任何给定时间实际需要显示的行调用.

The way Apple implements UITableView is not intuitive to everyone and it's easy to misunderstand the role of heightForRowAtIndexPath:. The general intention is that this is a faster and light-on-memory method that can be called for every row in the table quite frequently. This contrasts with cellForRowAtIndexPath: which is often slower and more memory intensive, but is only called for the rows that are actually need to be displayed at any given time.

为什么苹果要这样实现?部分原因是计算行的高度几乎总是比构建和填充整个单元格更便宜(或者如果您编码正确,则可能更便宜).鉴于在许多表格中,每个单元格的高度都是相同的,因此通常要便宜得多.另一部分原因是因为 iOS 需要知道整个表格的大小:这允许它创建滚动条并将其设置在滚动视图等上.

Why do Apple implement it like this? Part of the reason is that it's almost always cheaper (or can be cheaper if you code it right) to calculate the height of a row than it is to build and populate a whole cell. Given that in many tables the height of every cell will be identical, it is often vastly cheaper. And another part of the reason is because iOS needs to know the size of the whole table: this allows it to create the scroll bars and set it up on a scroll view etc.

因此,除非每个单元格的高度都相同,否则当创建 UITableView 并且每次向其发送 reloadData 消息时,数据源都会为每个单元格发送一个 heightForRowAtIndexPath 消息.因此,如果您的表格有 30 个单元格,则该消息将发送 30 次.假设这 30 个单元格中只有 6 个在屏幕上可见.在这种情况下,当创建并发送 reloadData 消息时,UITableView 将在每个可见行发送一个 cellForRowAtIndexPath 消息,即该消息被发送六次.

So, unless every cell height is the same, then when a UITableView is created and whenever you send it a reloadData message, the datasource is sent one heightForRowAtIndexPath message for each cell. So if your table has 30 cells, that message gets sent 30 times. Say only six of those 30 cells are visible on screen. In that case, when created and when you send it a reloadData message, the UITableView will send one cellForRowAtIndexPath message per visible row, i.e. that message gets sent six times.

有些人有时会对如何在不自己创建视图的情况下计算单元格高度感到困惑.但通常这很容易做到.

Some people are sometimes puzzled about how to calculate a cell height without creating the views themselves. But usually this is easy to do.

例如,如果您的行高因包含不同数量的文本而大小不同,您可以对相关字符串使用 sizeWithFont: 方法之一进行计算.这比构建视图然后测量结果更快.请注意,如果您更改单元格的高度,您将需要重新加载整个表格(使用 reloadData - 这将要求委托提供每个高度,但只要求提供可见单元格)或有选择地重新加载大小具有的行改变了(上次我检查时,它也在每行上调用 heightForRowAtIndexPath: 也做了一些滚动工作以进行良好的测量).

For example, if your row heights vary in size because they hold varying amounts of text, you can use one of the sizeWithFont: methods on the relevant string to do the calculations. This is quicker than building a view and then measuring the result. Note, that if you change the height of a cell, you will need to either reload the whole table (with reloadData - this will ask the delegate for every height, but only ask for visible cells) OR selectively reload the rows where the size has changed (which, last time I checked, also calls heightForRowAtIndexPath: on ever row but also does some scrolling work for good measure).

参见 这个问题,也许还有这个问题.

这篇关于Iphone - 当每个单元格高度是动态的时,何时计算 tableview 的 heightForRowAtIndexPath?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆