修改 SwiftUI 中 @State 数组内部结构中的值

问题描述 投票:0回答:1

在 SwiftUI 中,我有一组结构,当按下按钮时,我想更改其中一个的值(并让 UI 自动更新)。

我对数组使用@State,所以我觉得这应该可行,但我遇到了很多问题,我所做的更改没有反映在数组中。

我在here看到了类似的帖子,并尝试了那里列出的一些方法,但似乎都不起作用。下面是主要相关代码的简化版本,它使用了该帖子中的想法之一(使用过滤器)。

奇怪的是,我发现即使我创建一个全新的数组然后设置“items = newItems”,它也不起作用。我唯一的部分解决方法是创建 newItems,然后删除项目中的所有值并添加 newItems 中的值(这看起来像是一个彻底的黑客)。

struct Item: Codable, Identifiable {
    var id: Int
    var value: Int
}

struct ContentView: View {
    @State private var items: [Item] = []

    var body: some View {
        NavigationStack {
            List {
                ForEach (items) { item in
                // I am expecting this to be called when I update items[], however it is never called.
                }
            }
            Button("test", action: {
                updateValueOfItem(1, 100)
            }
         }
    }

    func updateValueOfItem(id: Int, value: Int)
    {
        items.indices.filter { items[$0].id == id }
        .forEach { items[$0].value = value }
        //items[0].value = value // this doesn't work either
        print("array = \(items)") // shows old value, not new one!
    }
}

更新:我读到类和结构的处理方式不同,因此我尝试将 Item 结构更改为类,但没有帮助。

swift swiftui
1个回答
0
投票

尝试使用

.onAppear
填充项目数组, 然后调用您的函数来更改所选索引的值。

示例代码显示结构体数组已根据需要更改,即 实现您的目标

...when a button is pressed I want to change a value of one of them (and have the UI automatically update)

struct Item: Codable, Identifiable {
    var id: Int
    var value: Int
}

struct ContentView: View {
    @State private var items: [Item] = []
    
    var body: some View {
        NavigationStack {

            List {
                HStack {
                    Text("id")
                    Spacer()
                    Text("value")
                }
                ForEach (items) { item in
                    HStack {
                        Text("\(item.id)")
                        Spacer()
                        Text("\(item.value)")
                    }
                }
            }
            Button("test") {
                updateValueOfItem(id: 1, value: 100)
            }
        }
        .onAppear {
            // give the items some values
            items = [Item(id: 0, value: 0), Item(id: 1, value: 1), Item(id: 2, value: 2)]
        }
    }

    func updateValueOfItem(id: Int, value: Int) {
        // initially the array is empty, because you have `... var items: [Item] = []`
        // so filter will always be empty as well
        items.indices.filter { items[$0].id == id }.forEach { items[$0].value = value }
        print("array = \(items)")
    }
    
}
© www.soinside.com 2019 - 2024. All rights reserved.