Создание серии основных списков сведений из одного файла JSON в SwiftUI - PullRequest
1 голос
/ 31 октября 2019

Я пытаюсь понять, как правильно организовать поток данных через приложение, которое я создаю. Мне просто нужен базовый основной подробный вид, где он начинается со списка всех объектов верхнего уровня (пользователей), нажатие на один из них позволяет увидеть все объекты второго уровня, связанные с этим верхним уровнем (userX -> city), и нажатиеодин из них позволяет вам видеть все объекты третьего уровня (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 Предварительный просмотр:

UserList.swift Preview

Чего я не могу понять, так это как написать CityList / CityRow и TownList / TownRow так, чтобы я мог перейти вниз с главного экрана и получитьсписок, связанный с возражением, к которому я подключился.

Ответы [ 2 ]

2 голосов
/ 31 октября 2019

Ваши CityModel и TownModel должны соответствовать Identifiable, просто добавьте к ним идентификатор, как вы сделали в UserModel.

Чем нужно отредактировать свой UserList NavigationLink:

NavigationLink(destination: CityList(cities: user.cities)) {
    Text(user.firstName)
}

Навигация теперь выглядит следующим образом: UserList -> CityList -> TownList

CityList:

struct CityList: View {

    var cities: [CityModel]

    var body: some View {
        List (cities) { city in
            NavigationLink(destination: TownList(towns: city.towns)) {
                Text(city.name)
            }
        }
    }
}

TownList:

struct TownList: View {

    var towns: [TownModel]

    var body: some View {
        List (towns) { town in
            Text(town.name)
        }
    }
}

Надеюсь, это поможет, в моем тестовом проекте это работает!

2 голосов
/ 31 октября 2019

сначала вы должны создать 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)
}
...

Другой способ - объявить переменную «города» в виде массива CityModel и получить ее от пользователя:

struct CityListView: View {
    var cities: [UserModel]
    // list for array of cities
}

// in UserList
NavigationLink(destination: CityListView(cities: user.cities)) {
    UserRow(user: user)
}

PS Apple сделала отличный учебник поНавигация в SwiftUI: https://developer.apple.com/tutorials/swiftui/building-lists-and-navigation

...