[英]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.hidden
为false
或只是没有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.