gpt4 book ai didi

ios - SwiftUI @Published 属性不更新 View

转载 作者:行者123 更新时间:2023-12-04 07:51:56 26 4
gpt4 key购买 nike

在下面的代码中,点击 FavoriteButton 时详细 View UI 不会更新。我们知道绑定(bind)连接到 ObservableObject 因为 didSet被调用并打印 foos 的更新状态大批。奇怪的是,我发现添加一个 VStackFooListNavigationView解决了这种情况下的错误,但没有解决我遇到此问题的更复杂的 UI。
我是否缺少有关如何连接的信息?另一种解决方法是切换 State FavoriteButton 中的 bool 值,但这似乎违背了绑定(bind)的观点。

import SwiftUI

struct Foo: Identifiable {
var id = UUID()
var name: String
var isFavorite: Bool
}

class FooData: ObservableObject {
@Published var foos = [Foo(name: "Test", isFavorite: true)] {
didSet {
print(foos)
}
}
}

struct FooList: View {
@ObservedObject var fooData = FooData()

var body: some View {
NavigationView {
// Adding a VStack makes the FavoriteButton update correctly, but this doesn't work for more complicated UIs
// VStack {
List {
ForEach(fooData.foos, id: \.id) { foo in
let index = fooData.foos.firstIndex(where: { $0.id == foo.id })!
NavigationLink(foo.name, destination: FooDetailView(foo: $fooData.foos[index]))
}
}
// }
}
}
}

struct FooDetailView: View {
@Binding var foo: Foo

var body: some View {
FavoriteButton(isFavorite: $foo.isFavorite)
}
}

struct FavoriteButton: View {
@Binding var isFavorite: Bool

var body: some View {
Button(action: {
isFavorite.toggle()
}, label: {
if isFavorite {
Image(systemName: "heart.fill")
} else {
Image(systemName: "heart")
}
})
}
}
更新:
路过 FooData作为 EnvironmentObjectList并声明 EnvironmentObjectFavoriteButton解决了这个问题。这必须足以告诉 SwiftUI 该 View 关心对 FooData 的任何更新。 ,即使没有代码引用 EnvironmentObject直接地。这感觉有点像魔术,对我来说绝对不是最直观的行为。希望这可以帮助其他人。
完整的工作代码:
import SwiftUI

struct Foo: Identifiable {
var id = UUID()
var name: String
var isFavorite: Bool
}

class FooData: ObservableObject {
@Published var foos = [Foo(name: "Test", isFavorite: true)] {
didSet {
print(foos)
}
}
}

struct FooList: View {
@ObservedObject var fooData = FooData()

var body: some View {
NavigationView {
List {
ForEach(fooData.foos, id: \.id) { foo in
let index = fooData.foos.firstIndex(where: { $0.id == foo.id })!
NavigationLink(foo.name, destination: FooDetailView(foo: $fooData.foos[index]))
}
}
}
.environmentObject(fooData)
}
}

struct FooDetailView: View {
@Binding var foo: Foo

var body: some View {
FavoriteButton(isFavorite: $foo.isFavorite)
}
}

struct FavoriteButton: View {
@EnvironmentObject var fooData: FooData
@Binding var isFavorite: Bool

var body: some View {
Button(action: {
isFavorite.toggle()
}, label: {
if isFavorite {
Image(systemName: "heart.fill")
} else {
Image(systemName: "heart")
}
})
}
}

最佳答案

当您有一个 viewModel 发布一个数组时,唯一可以触发 View 更新的是数组计数。所以你需要将数组中的对象设为 class , 将其扩展到 ObservableObject , 并制作 isFavorite一个 @Published var它会起作用的。

class Foo: Identifiable, ObservableObject {
var id = UUID()
var name: String
@Published var isFavorite: Bool

init(name: String, isFavorite: Bool) {
self.name = name
self.isFavorite = isFavorite
}
}
另外,你应该让你的 FooData一个 @StateObject因为这个 View 拥有它。
struct ContentView: View {
@StateObject var fooData = FooData()

var body: some View {
NavigationView {
List {
ForEach(fooData.foos) { foo in
NavigationLink(foo.name, destination: FooDetailView(foo: foo))
}
}
}
}
}
通过 foo降为 @ObservedObject
struct FooDetailView: View {
@ObservedObject var foo: Foo

var body: some View {
Button(action: {
foo.isFavorite.toggle()
}, label: {
if foo.isFavorite {
Image(systemName: "heart.fill")
} else {
Image(systemName: "heart")
}
})
}
}

关于ios - SwiftUI @Published 属性不更新 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66921673/

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