SwiftUI @Binding 不刷新视图
SwiftUI @Binding doesn't refresh View
我有一个简单的 master/detail 界面,其中详细视图修改数组中的项目。使用下面的代码,模型已正确更新,但 SwiftUI 不会刷新视图以反映更改。
型号:
struct ProduceItem: Identifiable {
let id = UUID()
let name: String
var inventory: Int
}
final class ItemStore: BindableObject {
var willChange = PassthroughSubject<Void, Never>()
var items: [ProduceItem] { willSet { willChange.send() } }
init(_ items: [ProduceItem]) {
self.items = items
}
}
显示 ProduceItems 列表的主视图(ItemStore 被插入到 SceneDelegate 的环境中):
struct ItemList: View {
@EnvironmentObject var itemStore: ItemStore
var body: some View {
NavigationView {
List(itemStore.items.indices) { index in
NavigationLink(destination: ItemDetail(item: self.$itemStore.items[index])) {
VStack(alignment: .leading) {
Text(self.itemStore.items[index].name)
Text("\(self.itemStore.items[index].inventory)")
.font(.caption)
.foregroundColor(.secondary)
}
}
}
.navigationBarTitle("Items")
}
}
}
可让您更改物品库存价值的详细信息视图:
struct ItemDetail: View {
@Binding var item: ProduceItem
var body: some View {
NavigationView {
Stepper(value: $item.inventory) {
Text("Inventory is \(item.inventory)")
}
.padding()
.navigationBarTitle(item.name)
}
}
}
点击 ItemDetail 视图中的步进器会修改商店中的项目,但步进器的文本不会更改。导航回列表确认模型已更改。此外,我确认该商店已向其发布商致电 willChange.send()
。我会假设 send()
调用更新了环境中的 ItemStore,详细视图的 @Binding
属性 应该被通知更改并刷新显示(但它没有)。
我尝试将 ItemDetail 的项目 属性 更改为使用 @State
:
@State var item: ProduceItem = ProduceItem(name: "Plums", inventory: 7)
在这种情况下,模型是项目在使用步进器时更新并刷新视图,显示更新后的库存。谁能解释为什么使用 @Binding
属性 不刷新界面,但本地 @State
属性 会刷新界面?
这里有一个解决方法。调用 ItemDetail 时使用索引,而不是元素。在 ItemDetail 中,您使用 @EnvironmentObject
.
struct ItemList: View {
@EnvironmentObject var itemStore: ItemStore
var body: some View {
NavigationView {
List(itemStore.items.indices) { index in
NavigationLink(destination: ItemDetail(idx: index)) {
VStack(alignment: .leading) {
Text(self.itemStore.items[index].name)
Text("\(self.itemStore.items[index].inventory)")
.font(.caption)
.foregroundColor(.secondary)
}
}
}
.navigationBarTitle("Items")
}
}
}
struct ItemDetail: View {
@EnvironmentObject var itemStore: ItemStore
let idx: Int
var body: some View {
NavigationView {
Stepper(value: $itemStore.items[idx].inventory) {
Text("Inventory is \(self.itemStore.items[idx].inventory)")
}
.padding()
.navigationBarTitle(itemStore.items[idx].name)
}
}
}
我有一个简单的 master/detail 界面,其中详细视图修改数组中的项目。使用下面的代码,模型已正确更新,但 SwiftUI 不会刷新视图以反映更改。
型号:
struct ProduceItem: Identifiable {
let id = UUID()
let name: String
var inventory: Int
}
final class ItemStore: BindableObject {
var willChange = PassthroughSubject<Void, Never>()
var items: [ProduceItem] { willSet { willChange.send() } }
init(_ items: [ProduceItem]) {
self.items = items
}
}
显示 ProduceItems 列表的主视图(ItemStore 被插入到 SceneDelegate 的环境中):
struct ItemList: View {
@EnvironmentObject var itemStore: ItemStore
var body: some View {
NavigationView {
List(itemStore.items.indices) { index in
NavigationLink(destination: ItemDetail(item: self.$itemStore.items[index])) {
VStack(alignment: .leading) {
Text(self.itemStore.items[index].name)
Text("\(self.itemStore.items[index].inventory)")
.font(.caption)
.foregroundColor(.secondary)
}
}
}
.navigationBarTitle("Items")
}
}
}
可让您更改物品库存价值的详细信息视图:
struct ItemDetail: View {
@Binding var item: ProduceItem
var body: some View {
NavigationView {
Stepper(value: $item.inventory) {
Text("Inventory is \(item.inventory)")
}
.padding()
.navigationBarTitle(item.name)
}
}
}
点击 ItemDetail 视图中的步进器会修改商店中的项目,但步进器的文本不会更改。导航回列表确认模型已更改。此外,我确认该商店已向其发布商致电 willChange.send()
。我会假设 send()
调用更新了环境中的 ItemStore,详细视图的 @Binding
属性 应该被通知更改并刷新显示(但它没有)。
我尝试将 ItemDetail 的项目 属性 更改为使用 @State
:
@State var item: ProduceItem = ProduceItem(name: "Plums", inventory: 7)
在这种情况下,模型是项目在使用步进器时更新并刷新视图,显示更新后的库存。谁能解释为什么使用 @Binding
属性 不刷新界面,但本地 @State
属性 会刷新界面?
这里有一个解决方法。调用 ItemDetail 时使用索引,而不是元素。在 ItemDetail 中,您使用 @EnvironmentObject
.
struct ItemList: View {
@EnvironmentObject var itemStore: ItemStore
var body: some View {
NavigationView {
List(itemStore.items.indices) { index in
NavigationLink(destination: ItemDetail(idx: index)) {
VStack(alignment: .leading) {
Text(self.itemStore.items[index].name)
Text("\(self.itemStore.items[index].inventory)")
.font(.caption)
.foregroundColor(.secondary)
}
}
}
.navigationBarTitle("Items")
}
}
}
struct ItemDetail: View {
@EnvironmentObject var itemStore: ItemStore
let idx: Int
var body: some View {
NavigationView {
Stepper(value: $itemStore.items[idx].inventory) {
Text("Inventory is \(self.itemStore.items[idx].inventory)")
}
.padding()
.navigationBarTitle(itemStore.items[idx].name)
}
}
}