在 SwiftUI 中从单个 JSON 文件创建一系列主要细节列表
Creating a series of master detail lists from a single JSON file in SwiftUI
我正在努力了解如何让数据在我正在构建的应用程序中顺畅流动。我只想要一个基本的主细节视图,它以所有顶级对象(用户)的列表开始,点击其中一个可以让您看到与该顶级(userX - >城市)相关的所有二级对象,然后点击其中之一可以让您看到所有第三级对象(userX -> cityX -> towns)。
这是我的 JSON 文件:
[
{
"id": 1001,
"first_name": "Jimmy",
"last_name": "Simms",
"cities": [{
"name": "New York City",
"towns": [{
"name": "Brooklyn"
},
{
"name": "Manhatten"
}
]
},
{
"name": "Tokyo",
"towns": [{
"name": "Churo"
},
{
"name": "Riponggi"
}
]
}
]
}
...
]
我有一个模型,我认为它很适合这个:
import SwiftUI
struct UserModel: Codable, Identifiable {
let id: Int
let firstName: String
let lastName: String
let cities: [CityModel]
enum CodingKeys: String, CodingKey {
case id
case firstName = "first_name"
case lastName = "last_name"
case cities
}
}
struct CityModel: Codable {
let name: String
let towns: [TownModel]
}
struct TownModel: Codable {
let name: String
}
但是,我正在努力做的是将这一切构建到一系列相互连接的列表视图中。我有顶级的,UserList.swift 至少显示了一个用户列表。
import SwiftUI
struct UserList: View {
var body: some View {
NavigationView {
List(userData) { user in
NavigationLink(destination: UserRow(user: user)) {
UserRow(user: user)
}
}
.navigationBarTitle(Text("Users"))
}
}
}
struct UserList_Previews: PreviewProvider {
static var previews: some View {
UserList()
}
}
这是辅助视图,UserRow:
import SwiftUI
struct UserRow: View {
var user: UserModel
var body: some View {
HStack {
VStack(alignment: .leading) {
Text(user.firstName)
.font(.headline)
Text(user.lastName)
.font(.body)
.foregroundColor(Color.gray)
}
Spacer()
}
}
}
struct UserRow_Previews: PreviewProvider {
static var previews: some View {
UserRow(user: userData[0])
}
}
UserList.swift 预览:
我想不通的是如何编写 CityList/CityRow 和 TownList/TownRow 以便我可以从主屏幕向下钻取并获得与我点击的对象相关的列表。
首先您必须创建 CityListView 和 CityRow,就像您为用户所做的那样:
struct CityListView: View {
var user: UserModel
var body: some View {
// don't forget to make CityModel Identifiable
List(user.cities) { city in
CityRowView(city: city)
}
.navigationBarTitle(Text("Cities"))
}
}
}
struct CityRowView: View {
var city: CityModel
var body: some View {
HStack {
Text(city. name)
.font(.headline)
Spacer()
}
}
}
之后您需要在 NavigationLink 中更改目的地(不是 UserRow,而是新的 CityListView)
...
//NavigationLink(destination: UserRow(user: user)) {
NavigationLink(destination: CityListView(user: user)) {
UserRow(user: user)
}
...
另一种方法是将变量 "cities" 声明为 CityModel 的数组并从用户接收它:
struct CityListView: View {
var cities: [UserModel]
// list for array of cities
}
// in UserList
NavigationLink(destination: CityListView(cities: user.cities)) {
UserRow(user: user)
}
P.S。 Apple 在 SwiftUI 中制作了出色的导航教程:https://developer.apple.com/tutorials/swiftui/building-lists-and-navigation
您的 CityModel 和 TownModel 需要符合 Identifiable,只需像在 UserModel 中那样为它们添加一个 id。
比你需要编辑你的 UserList NavigationLink:
NavigationLink(destination: CityList(cities: user.cities)) {
Text(user.firstName)
}
导航现在是这样的:UserList -> CityList -> TownList
城市列表:
struct CityList: View {
var cities: [CityModel]
var body: some View {
List (cities) { city in
NavigationLink(destination: TownList(towns: city.towns)) {
Text(city.name)
}
}
}
}
城镇列表:
struct TownList: View {
var towns: [TownModel]
var body: some View {
List (towns) { town in
Text(town.name)
}
}
}
希望对您有所帮助,在我的测试项目中它有效!
我正在努力了解如何让数据在我正在构建的应用程序中顺畅流动。我只想要一个基本的主细节视图,它以所有顶级对象(用户)的列表开始,点击其中一个可以让您看到与该顶级(userX - >城市)相关的所有二级对象,然后点击其中之一可以让您看到所有第三级对象(userX -> cityX -> towns)。
这是我的 JSON 文件:
[
{
"id": 1001,
"first_name": "Jimmy",
"last_name": "Simms",
"cities": [{
"name": "New York City",
"towns": [{
"name": "Brooklyn"
},
{
"name": "Manhatten"
}
]
},
{
"name": "Tokyo",
"towns": [{
"name": "Churo"
},
{
"name": "Riponggi"
}
]
}
]
}
...
]
我有一个模型,我认为它很适合这个:
import SwiftUI
struct UserModel: Codable, Identifiable {
let id: Int
let firstName: String
let lastName: String
let cities: [CityModel]
enum CodingKeys: String, CodingKey {
case id
case firstName = "first_name"
case lastName = "last_name"
case cities
}
}
struct CityModel: Codable {
let name: String
let towns: [TownModel]
}
struct TownModel: Codable {
let name: String
}
但是,我正在努力做的是将这一切构建到一系列相互连接的列表视图中。我有顶级的,UserList.swift 至少显示了一个用户列表。
import SwiftUI
struct UserList: View {
var body: some View {
NavigationView {
List(userData) { user in
NavigationLink(destination: UserRow(user: user)) {
UserRow(user: user)
}
}
.navigationBarTitle(Text("Users"))
}
}
}
struct UserList_Previews: PreviewProvider {
static var previews: some View {
UserList()
}
}
这是辅助视图,UserRow:
import SwiftUI
struct UserRow: View {
var user: UserModel
var body: some View {
HStack {
VStack(alignment: .leading) {
Text(user.firstName)
.font(.headline)
Text(user.lastName)
.font(.body)
.foregroundColor(Color.gray)
}
Spacer()
}
}
}
struct UserRow_Previews: PreviewProvider {
static var previews: some View {
UserRow(user: userData[0])
}
}
UserList.swift 预览:
我想不通的是如何编写 CityList/CityRow 和 TownList/TownRow 以便我可以从主屏幕向下钻取并获得与我点击的对象相关的列表。
首先您必须创建 CityListView 和 CityRow,就像您为用户所做的那样:
struct CityListView: View {
var user: UserModel
var body: some View {
// don't forget to make CityModel Identifiable
List(user.cities) { city in
CityRowView(city: city)
}
.navigationBarTitle(Text("Cities"))
}
}
}
struct CityRowView: View {
var city: CityModel
var body: some View {
HStack {
Text(city. name)
.font(.headline)
Spacer()
}
}
}
之后您需要在 NavigationLink 中更改目的地(不是 UserRow,而是新的 CityListView)
...
//NavigationLink(destination: UserRow(user: user)) {
NavigationLink(destination: CityListView(user: user)) {
UserRow(user: user)
}
...
另一种方法是将变量 "cities" 声明为 CityModel 的数组并从用户接收它:
struct CityListView: View {
var cities: [UserModel]
// list for array of cities
}
// in UserList
NavigationLink(destination: CityListView(cities: user.cities)) {
UserRow(user: user)
}
P.S。 Apple 在 SwiftUI 中制作了出色的导航教程:https://developer.apple.com/tutorials/swiftui/building-lists-and-navigation
您的 CityModel 和 TownModel 需要符合 Identifiable,只需像在 UserModel 中那样为它们添加一个 id。
比你需要编辑你的 UserList NavigationLink:
NavigationLink(destination: CityList(cities: user.cities)) {
Text(user.firstName)
}
导航现在是这样的:UserList -> CityList -> TownList
城市列表:
struct CityList: View {
var cities: [CityModel]
var body: some View {
List (cities) { city in
NavigationLink(destination: TownList(towns: city.towns)) {
Text(city.name)
}
}
}
}
城镇列表:
struct TownList: View {
var towns: [TownModel]
var body: some View {
List (towns) { town in
Text(town.name)
}
}
}
希望对您有所帮助,在我的测试项目中它有效!