首页 > 解决方案 > 如何在 SwiftUI 中使用 Dictionary 作为@Binding var

问题描述

我需要在 SwiftUI 中显示一个折叠菜单,可以将一个布尔值作为绑定 var 传递给子视图,但在尝试从字典中传递该值时卡住了。

见下面的代码:

struct MenuView: View {
    @EnvironmentObject var data: APIData
    @State var menuCollapsed:[String: Bool] = [:]
    @State var isMenuCollapsed = false;

// I am able to pass self.$isMenuCollapsed but self.$menuCollapsed[menuItem.name], why?

var body: some View {

            if data.isMenuSynced {
                List() {
                    ForEach((data.menuList?.content)!, id: \.name) { menuItem in
                        TopMenuRow(dataSource: menuItem, isCollapsed: self.$isMenuCollapsed)
                            .onTapGesture {
                                if menuItem.isExtendable() {
                                    let isCollapsed = self.menuCollapsed[menuItem.name]
                                    self.menuCollapsed.updateValue(!(isCollapsed ?? false), forKey: menuItem.name)
                                } else {
                                    print("Go to link:\(menuItem.url)")
                                }

                            }
                    }
                }
            }else {
                Text("Loading...")
            }
        }

}

在 ChildMenu 行中:

struct TopMenuRow: View {
    var dataSource: MenuItemData
    @Binding var isCollapsed: Bool

    var body: some View {
        ChildView(menuItemData)
            if self.isCollapsed {
                //display List of child data etc
            }
        }
    }
}

如果我只使用一个布尔值作为绑定变量,则代码运行正常,但是,如果我想使用字典来存储数组的每个状态,则会出现其他错误,请参见图片打击: 在此处输入图像描述

如果我使用上面的行,那很好。

知道如何解决吗?

谢谢

标签: bindingswiftui

解决方案


如何使用字典作为带有 State 属性包装器的可变值的存储?

正如 Asperi 所提到的,ForEach 要求数据源符合 RandomAccessCollection。此要求不适用于 State 属性包装器!

让我们在下一个片段中查看其中一种可能的方法(复制 - 粘贴 - 运行)

import SwiftUI

struct ContentView: View {

    @State var dict = ["alfa":false, "beta":true, "gamma":false]

    var body: some View {
        List {
            ForEach(Array(dict.keys), id: \.self) { (key) in
                HStack {
                    Text(key)
                    Spacer()
                    Text(self.dict[key]?.description ?? "false").onTapGesture {
                        let v = self.dict[key] ?? false
                        self.dict[key] = !v
                    }.foregroundColor(self.dict[key] ?? false ? Color.red: Color.green)
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

结果如下

在此处输入图像描述


推荐阅读