[英]SwiftUI How to use View Model with nested JSON
我正在学习 iOS 开发,我正在尝试修改我的应用程序以使用 MVVM model。 下面我粘贴我正在使用的 json 结构。 我可以访问类别,但是当我尝试遍历 Items 时遇到了问题。 我的观点 model 应该是什么样子? 我需要 2 个视图模型,一个用于类别,另一个用于项目吗? 另外如何将 View Model 与 AppStorage 结合使用?
[
{
"id": "8DC6D7CB-C8E6-4654-BAFE-E89ED7B0AF94",
"name": "Category",
"items": [
{
"id": "59B88932-EBDD-4CFE-AE8B-D47358856B93",
"name": "Item1",
"isOn": false
},
{
"id": "E124AA01-B66F-42D0-B09C-B248624AD228",
"name": "Item2",
"isOn": false
}
}
]
看法
struct ContentView: View {
@ObservedObject var viewModel = MyModel()
var body: some View {
List {
ForEach(viewModel.items, id: \.self) { id in
Text(id.name)
//how to iterate through items?
}
}
}
}
视图模型
class MyModel: ObservableObject {
@Published var items: [ItemsSection] = [ItemsSection]()
init(){
loadData()
}
func loadData() {
guard let url = Bundle.main.url(forResource: "items", withExtension: "json")
else {
print("Json file not found")
return
}
let data = try? Data(contentsOf: url)
let items = try? JSONDecoder().decode([ItemsSection].self, from: data!)
self.items = items!
}
func getSelectedItemsCount() -> Int{
var i: Int = 0
for itemSection in items {
let filteredItems = itemSection.items.filter { item in
return item.isOn
}
i = i + filteredItems.count
}
return i
}
}
Model:
struct ItemSection: Codable, Identifiable, Hashable {
var id: UUID = UUID()
var name: String
var items: [Item]
}
struct Item: Codable, Equatable, Identifiable,Hashable {
var id: UUID = UUID()
var name: String
var isOn: Bool = false
}
要遍历您的items
数组,您可以执行以下操作:
struct ContentView: View {
// This should be @StateObject as this View owns the viewmodel
@StateObject var viewModel = MyModel()
var body: some View {
List {
//ItemSection is Identifiable so no need for `id: \.self` here.
ForEach(viewModel.sections) { section in
//Section is a View provided by Apple that can help you laying
// out your View. You don´t have to, you can use your own
Section(section.name){
ForEach(section.items){ item in
Text(item.name)
}
}
}
}
}
}
我已经更改了 Viewmodel 中的命名,因为我认为items
var 的命名实际上应该是sections
。
class MyModel: ObservableObject {
@Published var sections: [ItemsSection] = [ItemsSection]()
init(){
loadData()
}
func loadData() {
guard let url = Bundle.main.url(forResource: "items", withExtension: "json")
else {
print("Json file not found")
return
}
do {
let data = try Data(contentsOf: url)
let sections = try JSONDecoder().decode([ItemsSection].self, from: data)
self.sections = sections
} catch {
print("failed loading or decoding with error: ", error)
}
}
func getSelectedItemsCount() -> Int{
var i: Int = 0
for itemSection in sections {
let filteredItems = itemSection.items.filter { item in
return item.isOn
}
i = i + filteredItems.count
}
return i
}
}
并且从不使用try?
使用正确的do / catch
块并打印错误。 这将帮助您在未来更好地发现问题。 例如,您提供的示例 JSON 格式错误。 如果没有正确的do / catch
它只会在强制展开时崩溃。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.