SwiftUI @Binding不会刷新视图 [英] SwiftUI @Binding doesn't refresh View

查看:38
本文介绍了SwiftUI @Binding不会刷新视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的主/明细接口,其中明细视图修改了数组中的项目.使用以下内容,可以正确更新模型,但是SwiftUI不会刷新视图以反映更改.

I have a simple master/detail interface where the detail view modifies an item in an array. Using the below, the model is updated properly, but SwiftUI doesn't refresh the View to reflect the change.

型号:

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中的环境中):

Master view that displays a list of ProduceItems (an ItemStore is inserted into the environment in the 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")
        }
    }
}

详细信息视图,可用于更改物料的库存值:

Detail view that lets you change the inventory value of an item:

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 属性并刷新显示(但它不会't).

Tapping on the stepper in the ItemDetail view modifies the item in the store, but the text of the stepper doesn't change. Navigating back to the list confirms the model has been changed. Also, I confirmed that the store calls willChange.send() to its publisher. I would assume that the send() call updates the ItemStore in the environment and the detail view's @Binding property should be notified of the change and refresh the display (but it doesn't).

我尝试将ItemDetail的item属性更改为使用 @State :

I tried changing ItemDetail's item property to use @State:

@State var item: ProduceItem = ProduceItem(name: "Plums", inventory: 7)

在这种情况下,使用步进器时将更新项目模型,并刷新视图,以显示更新的库存.谁能解释为什么使用 @Binding 属性不能刷新界面,而使用本地 @State 属性可以刷新界面吗?

In this case, the model is item is updated when using the stepper and the view is refreshed, displaying the updated inventory. Can anyone explain why using the @Binding property doesn't refresh the interface, but a local @State property does?

推荐答案

在这里,您有一种解决方法.调用ItemDetail时,使用索引而不是元素.在ItemDetail内,您使用 @EnvironmentObject .

Here you have a workaround. Use the index, instead of the element when calling ItemDetail. And inside ItemDetail, you use the @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)
        }
    }
}

这篇关于SwiftUI @Binding不会刷新视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆