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("", isOn: $jsonDataList.enabled)
。我已经尝试了几种格式化它的方法,但它似乎总是 return 一个错误。我的计划是能够检查该框是否被选中,如果是,则在某处安装一个文件。
我想做的另一件事是仅显示 JSON 中具有 jsonDataList.hidden
和 false
或没有 jsonDataList.hidden
的项目.
要完成这项工作,需要做几件事。首先是您的模型可能应该 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 一起使用。因为您的模型在一个数组中,所以 Binding 需要知道要更新哪个项目(它在数组中的索引)。您会在我的代码中看到 enabledBindingForIndex
函数。
最后,为了获得您将传递给 enabledBindingForIndex
函数的每个项目的索引,必须稍微更改 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 { [=11=].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
为 enabled/disabled 时产生一些副作用,您可以在 enabledBindingForIndex
set
闭包中这样做。
昨天,我问了一个相关问题
@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("", isOn: $jsonDataList.enabled)
。我已经尝试了几种格式化它的方法,但它似乎总是 return 一个错误。我的计划是能够检查该框是否被选中,如果是,则在某处安装一个文件。
我想做的另一件事是仅显示 JSON 中具有 jsonDataList.hidden
和 false
或没有 jsonDataList.hidden
的项目.
要完成这项工作,需要做几件事。首先是您的模型可能应该 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 一起使用。因为您的模型在一个数组中,所以 Binding 需要知道要更新哪个项目(它在数组中的索引)。您会在我的代码中看到 enabledBindingForIndex
函数。
最后,为了获得您将传递给 enabledBindingForIndex
函数的每个项目的索引,必须稍微更改 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 { [=11=].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
为 enabled/disabled 时产生一些副作用,您可以在 enabledBindingForIndex
set
闭包中这样做。