swift - 如何删除已经渲染的不需要的视图而不是渲染需要的视图?
问题描述
我正在开发一个CustomForEach,它可以像 SwiftUI 中的普通 ForEach 一样工作和工作,这个CustomForEach有它自己的早期版本,它有一些问题可供我使用,这让我更多地了解 SwiftUI 并挑战我尝试解决问题,其中一个问题是找到一种方法来破坏渲染所有需要的视图的不需要的视图!
目前,当我更新lowerBound时,CustomForEach开始渲染新范围,这是可以理解的。但是新范围需要比以前更少的视图,对于已经渲染的视图再次渲染它们是不可理解的。
目标:我想找到一种方法来停止渲染所有需要的视图,因为它们已经存在并且不需要再次渲染,只需删除不需要的视图。而且我不想在CustomForEach中开始另一个昂贵的计算来找出视图是否已经存在!
struct TextView: View {
let string: String
var body: some View {
print("rendering " + string)
return HStack {
Text(string)
Circle().fill(Color.red).frame(width: 5, height: 5, alignment: .center)
}
}
}
struct CustomForEachView<Content: View>: View {
private let id: Int
let range: ClosedRange<Int>
let content: (Int) -> Content
init(range: ClosedRange<Int>, @ViewBuilder content: @escaping (Int) -> Content) {
self.id = range.lowerBound
self.range = range
self.content = content
}
// The issue is rendering all existed Views when lower Bound get updated, even we do not need to render new View in updating lower Bound!
var body: some View {
content(range.lowerBound)
if let suffixRange = suffix(of: range) {
CustomForEachView(range: suffixRange, content: content)
}
}
private func suffix(of range: ClosedRange<Int>) -> ClosedRange<Int>? {
return (range.count > 1) ? (range.lowerBound + 1)...range.upperBound : nil
}
}
struct ContentView: View {
@State private var lowerBound: Int = -2
@State private var upperBound: Int = 2
var body: some View {
HStack {
CustomForEachView(range: lowerBound...upperBound) { item in
TextView(string: item.description)
}
}
HStack {
Button("add lowerBound") { lowerBound += 1 }
Spacer()
Button("add upperBound") { upperBound += 1 }
}
.padding()
}
}
解决方案
首先,要理解的重要一点是SwiftUI.View
结构不是在屏幕上呈现的视图实例。它只是对所需视图层次结构的描述。无论如何,这些实例都会被框架SwiftUI.View
重新创建和拆除。
SwiftUI 框架负责实际的渲染。它可能会为此使用 UIViews,也可能不会。在大多数情况下,这是您无需担心的实现细节。
也就是说,您可以通过使用id
修饰符向视图添加显式 ID 来帮助框架。这样 SwiftUI 可以使用它来跟踪哪个视图是哪个视图。
但是,我不确定这是否真的有帮助。只是一个想法。
推荐阅读
- javascript - 异步/等待示例不起作用。我究竟做错了什么
- sql - COUNT() 函数不适用于 oracle 中的 ID?检查了网站上的所有主题,没有人适合我
- android - 片段的状态没有被保留
- python - Python:有没有办法找到并删除字符串中第一次和最后一次出现的字符?
- android - 我的数据库有问题:“递归调用getDatabase”
- kubernetes - 在 EKS (Kubernetes) 和 ELB 中使用 gunicorn 和 django 实现高延迟
- bash - '4.5:语法错误:算术运算符无效(错误标记为“.5”)' - 但代码似乎仍然有效。为什么?
- reactjs - 在 Redux 中更新深度嵌套的状态
- kubernetes-helm - Minikube 上的 Helm:更新本地镜像
- r - 为 5 个不同变量的所有可能组合创建平均值