繁体   English   中英

MacOS - 使用 JSON 格式化带有复选框的 SwiftUI 列表(续)

[英]MacOS - Using JSON to format SwiftUI list with checkboxes (continued)

昨天,我在这里问了一个相关的问题。 我现在有这个脚本:

@available(OSX 11.0, *)
struct Mods_UI: View {
    @State private var falseerror = false
    @State var jsonDataList = [jsonData]()

    var body: some View {
        VStack {
            List(jsonDataList, id: \.id) { jsonDataList in
                VStack(alignment: .leading) {
                    HStack {
                        VStack(alignment: .leading) {
                            Text(jsonDataList.display)
                                .font(.title3)
                                .fontWeight(.bold)
                            Text(String(jsonDataList.description))
                                .font(.subheadline)
                        }
                        Spacer()
                        Image(systemName: jsonDataList.enabled ?? false ? "checkmark.square": "square")
                    }
                    Spacer()
                }
            }
            .onAppear(perform: loadData)
        }
    }

    func loadData() {

        guard let modsURL = URL(string: "https://raw.githubusercontent.com/nacrt/SkyblockClient-REPO/main/files/mods.json") else {
            print("Invalid URL")
            return
        }

        let task = URLSession.shared.dataTask(with: modsURL) { (data, _, error) in
            if let error = error { print(error); return }
            do {
                let result = try JSONDecoder().decode([jsonData].self, from: data!)
                jsonDataList = result
                print("Response:",jsonDataList)
            } catch {
                print(error)
            }
        }
        task.resume()
    }

}

@available(OSX 11.0, *)
struct Mods_UI_Previews: PreviewProvider {
    static var previews: some View {
        Mods_UI()
    }
}

struct jsonData: Codable, Identifiable {
    let id: String
    let display: String
    let description: String
    let url: String?
    let config: Bool?
    let enabled: Bool?
    let hidden: Bool?
    let icon: String?
    let categories: [String]?
}

我想将复选框: Image(systemName: jsonDataList.enabled?? false? "checkmark.square": "square")格式化为 Toggle: Toggle("", isOn: $jsonDataList.enabled) 我已经尝试了几种格式化它的方法,它似乎总是返回一个错误。 我的计划是能够检查该框是否被选中,如果是,则在某处安装一个文件。

我想做的另一件事是仅显示 JSON 中具有jsonDataList.hiddenfalse或只是没有jsonDataList.hidden的项目。

为了完成这项工作,需要做几件事。 第一个是您的 model 可能应该enabled var而不是let - 这样,在操作Toggle时可以更改其值:

struct jsonData: Codable, Identifiable {
    let id: String
    let display: String
    let description: String
    let url: String?
    let config: Bool?
    var enabled: Bool? //<-- Here
    let hidden: Bool?
    let icon: String?
    let categories: [String]?
}

接下来,您需要创建一个与 Toggle 一起使用的绑定。 因为您的 model 位于数组中,所以 Binding 需要知道要更新哪个项目(它在数组中的索引)。 你会在我的代码中看到它是enabledBindingForIndex function。

最后,为了获取您将传递给enabledBindingForIndex function 的每个项目的索引,必须稍微更改ForEach代码,以便它同时传递 JSON 项目索引。 我喜欢为此使用.enumerated() 请注意,该项目的id现在是.1.id因为您将获得一个包含索引 ( .0 ) 和项目 ( .1 ) 的元组。 我还过滤掉了同一行中的隐藏项目。


struct Mods_UI: View {
    @State private var falseerror = false
    @State var jsonDataList = [jsonData]()

    func enabledBindingForIndex(index: Int) -> Binding<Bool> {
        Binding<Bool> { () -> Bool in
            return jsonDataList[index].enabled ?? false
        } set: { (newValue) in
            jsonDataList[index].enabled = newValue
        }
    }
    
    var body: some View {
        VStack {
            List(Array(jsonDataList.filter { $0.hidden != true }.enumerated()),  //<-- Here
                 id: \.1.id) { (index,jsonDataList) in //<-- Here
                VStack(alignment: .leading) {
                    HStack {
                        VStack(alignment: .leading) {
                            Text(jsonDataList.display)
                                .font(.title3)
                                .fontWeight(.bold)
                            Text(String(jsonDataList.description))
                                .font(.subheadline)
                        }
                        Spacer()
                        Toggle(isOn: enabledBindingForIndex(index: index)) { } //Here
                    }
                    Spacer()
                }
            }
            .onAppear(perform: loadData)
        }
    }

    func loadData() {

        guard let modsURL = URL(string: "https://raw.githubusercontent.com/nacrt/SkyblockClient-REPO/main/files/mods.json") else {
            print("Invalid URL")
            return
        }

        let task = URLSession.shared.dataTask(with: modsURL) { (data, _, error) in
            if let error = error { print(error); return }
            do {
                let result = try JSONDecoder().decode([jsonData].self, from: data!)
                jsonDataList = result
                print("Response:",jsonDataList)
            } catch {
                print(error)
            }
        }
        task.resume()
    }

}

如果您想在启用/禁用Toggle时产生一些副作用,您可以在enabledBindingForIndex set闭包中执行此操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM