Swift 如果变量在数组中,则不刷新按钮标签

Swift 如果变量在数组中,则不刷新按钮标签,swift,swiftui,Swift,Swiftui,如果变量来自数组,则标签不会自动刷新。有没有具体的原因 @State private var categories: [ItemCategory] = getCategories() @State private var isOn = true Button(action: { categories[1].chose = !categories[1].chose }, label: { Text(categories[1].chose ? "Add" : &q

如果变量来自数组,则标签不会自动刷新。有没有具体的原因

@State private var categories: [ItemCategory] = getCategories()
@State private var isOn = true
Button(action: {
    categories[1].chose = !categories[1].chose
}, label: {
    Text(categories[1].chose ? "Add" : "Remove") // not automatically refreshed, only with view change (go to an other and then back)
})

Button(action: {
    isOn = !isOn
}, label: {
    Text(isOn ? "Add" : "Remove") // automatically refreshed
})
更新:

对不起,我错过了商品分类

class ItemCategory: Codable, Equatable, Identifiable, Hashable {
    var name: String
    var items: [Item]
    var chose: Bool
    var collapsed: Bool
}

更好地使用状态对象

@StateObject var categories: Categories = ...
其中:

class Categories : ObservableObject {
    @Published var list: [ItemCategory] = []
    init() {...}

    update(index: Int, row: ItemCategory) {
        self.objectWillChange.send()

        list[index] = row
    }
}
要从@Published更新视图,请执行以下操作:

objectWillChange.send()

您可以在视图中进行更改:

Button(action: {
    categories.objectWillChange.send()

    categories.list[1].chose = !categories.list[1].chose
}, label: {
    Text(categories[1].chose ? "Add" : "Remove") // not automatically refreshed, only with view change (go to an other and then back)
})
用于刷新UI(观察值并在其上更新)

创建预览:

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(list: CategoryList())
    }
}
为类别创建自定义模型类

class ItemCategory {
     var chose: Bool = false
}
为类别创建模型结构,无需发送对象更改通知

struct ItemCategory {
    var chose: Bool = false
}
创建静态列表数组观察值(您可以指定数据列表)

在内容视图中观察按钮文本更新

struct ContentView: View {
    @ObservedObject var list: CategoryList
    var body: some View {
        Button(action: {
            list.items[1].chose = !list.items[1].chose
            /// If using a custom model as class, then we have to send notification to update otherwise commenting this line
            list.objectWillChange.send() // send manually update notification cos class is not auto update support
        }, label: {
            Text(list.items[1].chose ? "Add" : "Remove")
        })
    }
}

出现此问题的原因是
itemcegory
是一个类。无论何时更改其属性,对象都保持不变。
@State
属性包装器在包装的对象更改时做出反应,而不仅仅是在其属性更改时

在这里,您可以找到有关类和结构之间差异的更多信息:


解决问题的最简单方法是将
itemcegory
更改为结构(也可能更改
Item
):

或者,如果希望
itemcegory
保持类,可以删除category对象并将其再次插入到集合中:

Button(action: {
    let category = categories.remove(at: 1)
    category.chose.toggle()
    categories.insert(category, at: 1)
}, label: {
    Text(categories[1].chose ? "Add" : "Remove")
})

它一定在工作,你的代码没有问题,你能显示ItemCategory的结构吗?如果没有它,就不可能帮助你进行故障排除。
ItemCategory
是一个类吗?请为其添加代码。Itemcategory结构还是类?如果它是一个类,它就不能与@State包装器一起工作。更改为ObservedObject包装。为什么同时使用objectWillChange.send()和@published来观察一个属性?另外,在附加到数组之前调用objectWillChange.send()。
struct ContentView: View {
    @ObservedObject var list: CategoryList
    var body: some View {
        Button(action: {
            list.items[1].chose = !list.items[1].chose
            /// If using a custom model as class, then we have to send notification to update otherwise commenting this line
            list.objectWillChange.send() // send manually update notification cos class is not auto update support
        }, label: {
            Text(list.items[1].chose ? "Add" : "Remove")
        })
    }
}
struct ItemCategory: Codable, Equatable, Identifiable, Hashable {
    var name: String
    var items: [Item]
    var chose: Bool
    var collapsed: Bool

    // ...
}
Button(action: {
    let category = categories.remove(at: 1)
    category.chose.toggle()
    categories.insert(category, at: 1)
}, label: {
    Text(categories[1].chose ? "Add" : "Remove")
})