布局缓存与性能
使用布局缓存提升效率。
布局缓存与性能 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。
为什么需要布局缓存
SwiftUI 可能会在一次布局过程中多次调用 sizeThatFits 和 placeSubviews。
如果计算成本较高,使用缓存就可以只计算一次并重复使用结果,避免重复工作。
缓存关联类型
Layout 协议具有一个关联的 Cache 类型,默认值为 Void。您可以定义自己的结构体来存储预先计算的结果。
struct FlowLayout: Layout {
struct CacheData {
var sizes: [CGSize] = []
}
typealias Cache = CacheData
}makeCache
请实现 makeCache(subviews:) 来构建初始缓存。SwiftUI 会在布局方法之前调用它一次,为您提供执行预先测量的机会。
func makeCache(subviews: Subviews) -> CacheData {
let sizes = subviews.map { $0.sizeThatFits(.unspecified) }
return CacheData(sizes: sizes)
}读取缓存
现在,布局方法会接收作为 inout 参数的 cache。请读取预先计算的值,而不是重新测量每个子视图。
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout CacheData) -> CGSize {
let height = cache.sizes.map(\.height).max() ?? 0
let width = cache.sizes.reduce(0) { $0 + $1.width }
return CGSize(width: width, height: height)
}updateCache
当子视图集合发生变化时,SwiftUI 会调用 updateCache(_:subviews:)。默认实现会通过 makeCache 重新构建缓存,但您也可以重写它来执行增量更新。
func updateCache(_ cache: inout CacheData, subviews: Subviews) {
cache.sizes = subviews.map { $0.sizeThatFits(.unspecified) }
}updateCache 何时触发
updateCache 会在子视图数量或标识发生变化时运行,而不是在每次几何属性调整时运行。缓存只依赖于子视图的数据,不要缓存依赖于提议尺寸的数据。
只缓存与提议无关的数据
一个常见错误是缓存依赖于提议尺寸的结果。提议可能在不同调用之间发生变化,因此依赖尺寸的结果必须重新计算,不能盲目缓存。
// OK to cache: intrinsic child sizes
// NOT OK to cache: row breaks (depend on proposed width)缓存固有尺寸
一种安全做法是缓存开销较大的 sizeThatFits(.unspecified) 结果,然后在每次调用时根据当前提议执行开销较低的换行计算。
struct CacheData { var intrinsic: [CGSize] = [] }
// wrapping uses cache.intrinsic + current maxWidth避免过早优化
对于少量简单的子视图,测量开销很低,而缓存反而会增加复杂性。请先进行性能分析;只有在测量确实成本较高时(例如文本、图像和嵌套布局),才考虑使用缓存。
缓存与值语义
缓存由 SwiftUI 所有,并以 inout 形式传递。请将它保持为没有视图引用的普通值类型,以便 SwiftUI 安全地管理其生命周期。
struct CacheData {
var sizes: [CGSize] // value types only
}衡量优化收益
请使用 SwiftUI 性能分析工具或简单的计数器,确认缓存确实减少了测量调用次数。没有测量依据的优化只是猜测。
快速检查:布局缓存
请测试您对布局缓存的理解。
回顾:布局缓存与性能
Layout 协议的 Cache 关联类型由 makeCache 构建,并由 updateCache 刷新,用于存储固有子视图尺寸等与提议无关的高成本工作结果。
请在每次调用时执行开销较低且依赖提议的计算。让缓存保持为无引用的值类型,避免过早缓存,并在增加复杂性之前通过性能分析确认收益。
常见问题解答
「布局缓存与性能」课时是免费的吗?
是的 — 「布局缓存与性能」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。
「布局缓存与性能」这节课中我会学到什么?
使用布局缓存提升效率。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Swift Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「布局缓存与性能」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Swift Academy 课中编写并运行代码吗?
能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- Layout 协议基础
- 测量子视图
- 构建流式布局
- 布局缓存与性能