gpt4 book ai didi

ios - SwiftUI - ObservableObject 性能问题

转载 作者:行者123 更新时间:2023-11-28 20:50:09 27 4
gpt4 key购买 nike

当 SwiftUI View 绑定(bind)到 ObservableObject 时,当被观察对象发生任何变化时, View 会自动重新加载 - 无论是否更改直接影响 View 。

这似乎会给非平凡的应用程序带来严重的性能问题。看这个简单的例子:

// 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)
}
}

这里我们有两个不相关的 View ,位于应用程序的不同部分。他们都观察到环境提供的共享 User 的变化。 NameView 允许您通过 TextField 编辑 User 的名称。 ImageView 显示用户的个人资料图片。

Screenshot

问题:NameView 中的每次击键,观察此User所有 View 都被迫重新加载它们的 View 整个正文内容。这包括 ImageView,它可能涉及一些昂贵的操作 - 例如下载大图像/调整大图像的大小。

这在上面的示例中很容易证明,因为每次在 TextField 中输入新字符时,都会记录 "Redrawing name""Redrawing image"

问题:我们如何改进 Observable/Environment 对象的使用,以避免不必要的 View 重绘?有没有更好的方法来构建我们的数据模型?

编辑:

为了更好地说明为什么这会成为一个问题,假设 ImageView 不仅仅显示静态图像。例如,它可能:

  • 异步加载图像,由 subview 的 initonAppear 方法触发
  • 包含运行动画
  • 支持拖放界面,需要本地状态管理

还有很多例子,但这些是我在当前项目中遇到的。在每一种情况下,重新计算 View 的 body 都会导致丢弃状态和一些昂贵的操作被取消/重新启动。

并不是说这是 SwiftUI 中的“错误”——但如果有更好的方法来构建我们的应用程序,我还没有看到 Apple 或任何教程提到过它。大多数示例似乎都倾向于在不解决副作用的情况下自由使用 EnvironmentObject。

最佳答案

为什么 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)
}
}
}

当我点击键盘键时输出:

Redrawing name
Redrawing image
Redrawing name
Redrawing name
Redrawing name
Redrawing name

关于ios - SwiftUI - ObservableObject 性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59039475/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com