hun*_*ley 5 macos ios swift swiftui
当 SwiftUIView
绑定到 时ObservableObject
,当观察到的对象内发生任何更改时,视图会自动重新加载- 无论更改是否直接影响视图。
这似乎会导致非平凡应用程序出现严重的性能问题。看这个简单的例子:
// Our observed model
class User: ObservableObject {
@Published var name = "Bob"
@Published var imageResource = "IMAGE_RESOURCE"
}
// Name view
struct NameView: View {
@EnvironmentObject var user: User
var body: some View {
print("Redrawing name")
return TextField("Name", text: $user.name)
}
}
// Image view - elsewhere in the app
struct ImageView: View {
@EnvironmentObject var user: User
var body: some View {
print("Redrawing image")
return Image(user.imageResource)
}
}
Run Code Online (Sandbox Code Playgroud)
这里我们有两个不相关的视图,位于应用程序的不同部分。他们都观察到User
环境提供的共享的变化。NameView
允许您User
通过 TextField编辑的名称。ImageView
显示用户的个人资料图片。
问题:在每次击键时NameView
,所有观察到这一点的视图User
都被迫重新加载它们的整个正文内容。这包括ImageView
,这可能涉及一些昂贵的操作 - 例如下载/调整大图像的大小。
这可以在上面的示例中轻松证明,因为每次您在 TextField 中输入新字符时都会记录"Redrawing name"
和"Redrawing image"
。
问题:我们如何改进 Observable/Environment 对象的使用,以避免不必要的视图重绘?有没有更好的方法来构建我们的数据模型?
为了更好地说明为什么这可能是一个问题,假设ImageView
不仅仅是显示静态图像。例如,它可能:
init
或onAppear
方法触发还有更多的例子,但这些是我在当前项目中遇到的。在这些情况中的每一种情况下,body
重新计算视图都会导致丢弃状态和一些昂贵的操作被取消/重新启动。
并不是说这是 SwiftUI 中的“错误”——但如果有更好的方法来构建我们的应用程序,我还没有看到 Apple 或任何教程提到它。大多数示例似乎都倾向于自由使用 EnvironmentObject 而没有解决副作用。
rob*_*off 10
为什么ImageView
需要整个User
对象?
回答:没有。
将其更改为仅获取它需要的内容:
struct ImageView: View {
var imageName: String
var body: some View {
print("Redrawing image")
return Image(imageName)
}
}
struct ContentView: View {
@EnvironmentObject var user: User
var body: some View {
VStack {
NameView()
ImageView(imageName: user.imageResource)
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我点击键盘按键时输出:
Redrawing name
Redrawing image
Redrawing name
Redrawing name
Redrawing name
Redrawing name
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1401 次 |
最近记录: |