gpt4 book ai didi

ios - 为什么在更改 View 的 id 时不会第二次调用 onAppear()?

转载 作者:行者123 更新时间:2023-12-05 09:26:10 26 4
gpt4 key购买 nike

我正在学习“Thinking in Swift UI”一书的示例。

我正在创建一个 Observable 对象

final class Contact: ObservableObject, Identifiable {
let id = UUID()
@Published var name: String
@Published var city: String
@Published var profile: String

init(name: String, city: String, profile: String) {
self.name = name
self.city = city
self.profile = profile
}
}

内容 View 定义为选择联系人的按钮列表。并将联系人存储为普通数组属性

struct ContentView: View {
@State var selection: Contact?
var contacts: [Contact]

var body: some View {
HStack {
ForEach(contacts) { contact in
Button(contact.name) {
self.selection = contact
}
}
}
if let c = selection {
Detail2(contact: c)
}
}
}

这里我们有 Detail View,它调用 id 修饰符来更改 View 的标识,并假设再次调用“onAppear”——这是行不通的

struct Detail: View {
@ObservedObject var contact: Contact
@StateObject var loader = ImageLoader()
var body: some View {
HStack {
loader.imageView
VStack {
Text(contact.name).bold()
Text(contact.city)
}
}
.id(contact.id)
.onAppear {
loader.load(image: contact.profile)
}
}
}

在这里我 mock 了 Loader

class ImageLoader: ObservableObject {

var image: String = ""
init() {
print("Initializer of Image Loader was called")
}

func load(image: String) {
print("Brrr.... loading image")
print("The image is: \(image)")
self.image = image
}
}

该应用被定义为传递联系人数组的内容 View :

@main
struct SwiftUILearning2App: App {

var body: some Scene {
WindowGroup {
ContentView(contacts: [ Contact(name: "name1", city: "city1", profile: "profile_1"),
Contact(name: "name2", city: "city2", profile: "profile_2")])
}
}
}

为什么 onAppear 没有出现 - 实际上 load.loader( ) 在分配新联系人时没有被调用?根据书 .id(contact.id) 调用 Detail View 的修饰符应该能够使 onAppear 再次被调用。

在没有 .id(contact.id 修饰符的示例之后,书中指出:

“第一次尝试时,这似乎可行,但是当我们更改联系人对象(例如,通过选择不同的人)时, View 永远不会重新加载图像。解决此问题的最简单方法是告诉 SwiftUI 它应该改变 View 的标识:"

完整代码链接如下: https://gist.github.com/pbrewczynski/63f2dfdba96dec2efcf7d81d304622f6

最佳答案

根据 swiftUI 文档:

When the proxy value specified by the id parameter changes, the identity of the view — for example, its state — is reset.

View 不会调用 onAppear() 方法,因为它没有被再次创建,改变它的状态和参数。我的建议是调用 onChange() 方法:

    .onChange(of: contact) { newValue in
loader.load(image: newValue.profile)
}

解决方案很多,但id修饰符通常用于:

  1. 重置状态值
  2. 触发转换
  3. 改进 ListView 性能

一篇文章here希望对您有所帮助

关于ios - 为什么在更改 View 的 id 时不会第二次调用 onAppear()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74178462/

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