在开发我最新的应用程序时,我偶尔会遇到我的 tableview 渲染问题,似乎我的 tableview 单元格没有足够的空间来适应每个部分。
直到最近,我一直在努力可靠地重现这个问题,在用尽我能想到的一切之后,我决定将这个 bug 的基本原理克隆到一个测试应用程序中,我最终设法用它重现了一个类似的问题,所以我终于找到了似乎成为错误的原因。
我的主应用程序使用自定义部分标题视图,并且需要自动高度尺寸行和部分标题,因为我包含动态内容,其中包括可以增长的文本,如果需要,它们都可以多行显示。在我的主应用程序中调试问题时,我很快尝试用默认的 tableview 部分标题替换我的自定义部分标题视图,并且仍然能够重现问题,所以这个测试应用程序使用带有自动 sectionHeaderHeights 的部分标题,我意识到这很奇怪,但同样自定义视图会出现问题,它仅使用普通标题会导致一个更简单的示例。
我已将我的项目副本上传到位于此处的 zip 文件中。
以及两个视频显示我的测试应用程序中的工作流工作正常,然后被自动 sectionHeaderHeight 破坏。这些视频在这里
下图显示了应用程序正常显示 2 个测试部分及其行之间的区别
然后用浮动的“第 2 节”标题中断第 2 节中的一行。
实际的相关代码在项目的 TableViewController 中
class TableViewController: CoreDataTableViewController<RowEntity>
{
private let setAutomaticDimensionSectionHeaderHeight=true
override func viewDidLoad()
{
super.viewDidLoad()
// Get dynamic section heights working
// its this that seems to be causing the rogue header bug.. setting our section height to automatic dimension!
if (setAutomaticDimensionSectionHeaderHeight)
{
tableView.sectionHeaderHeight = UITableViewAutomaticDimension // this must be the default as dynamic section headers work without this so long as there's an estimated section header height specified
}
tableView.estimatedSectionHeaderHeight = 50.0 // seems like this property is absolutely crucial to getting auto layout sized section headers working.. probably need something equivalent set to get cells to do the same?
// Do any additional setup after loading the view, typically from a nib.
createSectionsIfNeeded(context: AppDelegate.viewContext)
createFetchRequest()
}
您可以看到类常量 setAutomaticDimensionSectionHeaderHeight 可以设置为使 tableView.sectionHeaderHeight 初始化为 UITableViewAutomaticDimension。如果设置为自动,则会出现上述视频中显示的错误,即
- 使用条形按钮明显切换部分时
- 新的“第 2 节”标题立即出现在其所需位置
- 现有的“第 2 节”标题及其行都通过它向下滑动到正确的位置
- 当通过不可见地切换部分时
- 转到下一个视图控制器(通过选择表格行)并使用其切换表格视图部分按钮
- 并返回到 tableview
- 重复此操作,以便在 tableview 不在屏幕时隐藏第 1 部分及其行
- 显示一个虚拟的“第 2 节”标题浮动在添加第 1 节时的位置。
- 此虚拟标题附加到 tableview 并随之滚动,但当您将其滚动到视图顶部时,不会将其他真实部分标题推开
动画故障是我只在这个测试应用程序中注意到的,因为在我的主应用程序中,我总是在导航控制器的某些子视图中重现对屏幕外 tableview 的更改。尽管如前所述,浮动标题视图已经被发现,并且使我的应用程序看起来很糟糕,实际上通过隐藏一些 tableview 行来严重破坏它。当我第一次看到它时,我没有意识到标题是错误的并且浮动我认为这是我的 tableview 的其他问题。
我可能会在 Apple 上记录一个雷达,因为它看起来很破,但我想看看是否有人有任何想法。我见过一些人谈论自动截面高度的一般问题,并建议您只动态计算截面高度的大小。如果我可以相信自动布局在这一点上已经解决,那么我认为这是我可以尝试的我猜想通过在我的 sectionView 中添加组件视图的高度来做到这一点?
除此之外,我刚刚看过其他一些问答系列,例如
那个谈论可能试图将estimatedSectionHeaderHeight(和estimatedRowHeight)设置为0,我刚刚在我的测试应用程序中尝试过,它似乎确实“解决了”这个问题。后一个链接还引用了早期的 iOS 11 发行说明
表格视图现在默认使用估计高度,这也意味着单元格和部分页眉/页脚视图现在默认为自定大小。estimatedRowHeight、estimateSectionHeaderHeight 和estimatedSectionFooterHeight 属性的默认值现在是UITableViewAutomaticDimension,这意味着表格视图选择了一个估计的高度来使用。如果可能,您仍应为每个属性提供更准确的估计,这是您对实际高度平均值的最佳猜测。如果您在使用 iOS 11 SDK 构建应用程序时存在行为不同的现有表格视图代码,并且您不想采用自调整大小,则可以通过将估计高度设置为 0 来禁用估计高度来恢复之前的行为。每个估计的高度属性。(30197915)
这让我尝试只注释掉全部估计的SectionHeaderHeight 行以使用新的默认 iOS 11 行为。这似乎也行得通,并且通过这种描述听起来更可取,因为我知道我确实想要自我调整大小。注释虽然说你应该自己提供估计,当我这样做时确实会导致这些错误,所以在这个阶段苹果的建议似乎不好。
我需要让我的主应用程序再次恢复正常,看看这是否能解决问题。我确实记得,当第一次获得动态高度部分和行时,似乎需要将这些估计属性设置为某些东西才能真正让我的自动布局和多行文本标签正常工作以填充所需的空间(我可能在时间虽然我正在与所有参数搏斗,试图让事情正常进行)。当我可以很好地了解这些部分的估计大小通常是多少时,将其设置为 0 似乎是错误的,将其留空以采用默认的自我调整大小似乎是正确的,尽管我想如果我在早期的 iOS 上发布代码可能需要调整,因为可能无法很好地工作。
对此的任何更多想法将不胜感激!
干杯!
编辑
经过进一步测试,我似乎对将高度设置和估计高度设置为 0 修复事物过于乐观。我只能通过没有不适合我的主要应用程序用例的动态高度部分标题来解决问题
我通过并测试了各种选项的所有组合,结果如下
从 sectionHeaderHeight 的角度来看,不同的估计SectionHeaderHeights
- tableView.sectionHeaderHeight = 0
- 没有估计高度 == 0、45 或自动尺寸的标题
- tableView.sectionHeaderHeight = 60
- 标题都具有恒定的 60 高度,没有 UI 错误
- tableView.sectionHeaderHeight = UITableViewAutomaticDimension
- 没有标题,或者当估计的 headerheight 为 0 时 viewForHeaderCalled
- 如果估计的 headerheight 设置为数字或自动尺寸,则标题有错误
从具有不同 sectionHeaderHeights 的估计 sectionHeaderHeight 角度
- tableView.estimatedSectionHeaderHeight = 0
- 没有将 sectionHeaderHeight 设置为 0 的标题或自动维度没有调用 viewForHeader。
- headers 没有 headerHeight=60 的错误
- tableView.estimatedSectionHeaderHeight = 45
- 没有 sectionHeaderHeight == 0 的标题
- headers 固定为 60,没有 sectionHeaderHeight=60 的错误
- 标题自动调整大小,带有 sectionHeaderHeight==Automatic Dimension
- tableView.estimatedSectionHeaderHeight = UITableViewAutomaticDimension
- 如果 sectionHeaderHeight==0, Automatic Dimension, 带有错误的标题
- 在 sectionHeaderHeight=60 的情况下将标题固定在 60 且没有错误
基本上没有任何组合可以解决此问题,但保留了具有动态高度部分标题的能力