Group(subviewsof:): 视图可以作为输入并解析它的子视图,但不是对子视图逐个进行遍历,会传回所有解析的子视图集合
ContainerValues 容器值是一种新型键控存储类似于环境和偏好等概念,沿着整个视图层次结构向下传递,偏好值沿着整个视图层次结构向上传递,到每个包含视图,特别适合实现特定于容器的定制选项
Identity: 是SwiftUI在app的多次更新中识别相同或不同元素的方式
有2种不同的身份,一种是显示标识, 一种是结构身份,区分视图
Lifetime: 生命周期是SwiftUI随时追踪视图和数据存在的方式
state lifetime = view lifetime
Dependencies: 依赖关系是SwiftUI理解你的界面何时需要更新以及为什么需要更新
标识符的稳定性至关重要,不稳定的标识符会导致更短的生命周期,拥有一个稳定的标识符,也有助于提高性能,应为SwiftUI不需要为视图创建存储,并通过新图表进行搅动。SwiftUI使用生命周期来管理持久化存储,因此稳定的标识符对于避免状态丢失也很重要
解密SwiftUI 性能
使用 lldb Self._printChanges()打印解释SwiftUI请求视图主题的原因
可以使用 let _ = Self._printChanges()不要在release环境下使用!
从资源包中查找值也很耗费资源
字符串插值通常会很耗费资源,所以你应确保缓存任何经常使用的字符串
任何堆内存分配例如类绑定类型也会增加资源消耗(初始化时,定义好类型)
SwiftUI通过身份Identity来管理视图生命周期,身份Identity的改变意味着视图的改变
List { ForEach(dogs) { dog in
if dog.fetchToy == .ball {
Text("")
}
}
}
以上代码需要构建所有视图来检索行标识符,因为它不知道每个元素会解析为多少视图
/// 这样做在原型中可能有效,但当集合扩大时,这个操作可能很快会非常耗费资源
List {
ForEach(dogs.filter(...)) { dog in
if dog.fetchToy == .ball {
Text("")
}
}
}
因此最好是将其移出模型
List {
ForEach(toyDogs) { dog in
Text("")
}
}
产生的行数等于元素数乘以每个元素产生的视图数,你要确保每个元素的视图数量是恒定的,否则SwiftUI除了标识符之外,还必须构建所有视图才能识别行
Row count = element count x views per element