SwiftUI - список элементов во вложенном массиве - PullRequest
1 голос
/ 04 ноября 2019

Я пытаюсь отобразить элементы из массива верхнего уровня в виде списка. Модель данных построена таким образом, что это массив событий, а затем внутри этого массива есть массив мест, связанных с отдельными событиями.

На главном экране я знаю, как отобразить заголовок отдельного событияпо его индексу, но я не уверен, как использовать ForEach для перечисления всех различных событий.

Passports.swift (модель данных)

import Foundation
import SwiftUI


struct Passport: Identifiable {
    let id : Int
    let passportPremium: Bool
    let passportActive: Bool
    let passportTitle: String
    let passportDates: String
    let venues: [Venue]
}

struct Venue: Identifiable {

    let id = UUID()
    let title : String
    let venueArea: String
    let venueItems: [venueItem]
}

struct venueItem {
    let title: String
    let productDescription: String
    let productPrice: Double
    let productType: String
    let newStatus: Bool
    let diningPlan: Bool
    let kidFriendly: Bool
    let vegetarian: Bool
    let glutenFree: Bool
    let featuredProduct: Bool
    let containsAlcohol: Bool
}


extension Passport {
    static func all() -> [Passport] {
        return [
                Passport (
                    id: 1001,
                    passportPremium: false,
                    passportActive: true,
                    passportTitle : "Event 1",
                    passportDates: "October 20 - November 3, 2019",
                    venues: [
                        Venue (
                            title: "Bavaria Holiday Kitchen",
                            venueArea: "Germany Pavilion",
                            venueItems: [
                                venueItem (
                                    title: "Potato Dumpling",
                                    productDescription: "Potato Dumpling with Mushroom Sauce",
                                    productPrice: 0.00,
                                    productType: "Food",
                                    newStatus: false,
                                    diningPlan: false,
                                    kidFriendly: true,
                                    vegetarian: false,
                                    glutenFree: false,
                                    featuredProduct: false,
                                    containsAlcohol: false
                                )
                            ] // End VenueItems
                        ) // End Venue
                    ] // End Venues
                ),

                Passport (
                               id: 1002,
                               passportPremium: false,
                               passportActive: true,
                               passportTitle : “Event 2“,
                               passportDates: "October 20 - November 3, 2019",
                               venues: [
                                   Venue (
                                       title: "Bavaria Holiday Kitchen",
                                       venueArea: "Germany Pavilion",
                                       venueItems: [
                                           venueItem (
                                               title: "Potato Dumpling",
                                               productDescription: "Potato Dumpling with Mushroom Sauce",
                                               productPrice: 0.00,
                                               productType: "Food",
                                               newStatus: false,
                                               diningPlan: false,
                                               kidFriendly: true,
                                               vegetarian: false,
                                               glutenFree: false,
                                               featuredProduct: false,
                                               containsAlcohol: false
                                           )
                                       ] // End VenueItems
                                   ) // End Venue
                               ] // End Venues
                           )// End Individual Passport

                ] // End Return

    }

}

PassportsView.swift

import SwiftUI

struct PassportsView: View {

    var model = Passports.all()

    var body: some View {
        NavigationView {
            ForEach(self.model) { item in
                NavigationLink (destination: PassportDetails(passportTitle: item.passportTitle, venues: item.venues, venueProd: []) ) {
                HStack {
                    VStack(alignment: .leading) {
                        Text(item.passport[0].passportTitle)
                            .fontWeight(.semibold)
                            .foregroundColor(Color.white)
                        Text(item.passport[0].passportDates)
                            .foregroundColor(Color.white)
                    }.frame(width: 400, height: 120)
                        .background(Color("wPurple"))
                        .cornerRadius(6)
                }
              }.padding(.horizontal) 
            }
        }
    }
}

PassportDetails.swift

struct PassportDetails: View {

var passportTitle: String
var venues: [Venue]
var venueProd: [venueItem]

var body: some View {

    List {
        ForEach(self.venues) { gc in
            Section(header: Text(gc.title)) {
                ForEach(gc.venueItems, id: \.title) { gi in
                    GeometryReader { geometry in
                        VStack(alignment: .leading) {
                            HStack {
                                Text(gi.title)
                                    .frame(width: geometry.size.width / 1.5, alignment: .leading)
                                    .fixedSize(horizontal: false, vertical: true)
                                    .padding(.top, 10)
                                Spacer()
                                Text("$\(gi.productPrice, specifier: "%.2f")")
                                    .multilineTextAlignment(.trailing)

                            }.padding(.top, 8)
                            HStack {
                                Text(gi.productDescription)
                                    .font(.footnote)
                                    .foregroundColor(Color.gray)
                                    .frame(width: geometry.size.width / 1.5, alignment: .leading)
                                .fixedSize(horizontal: false, vertical: true)
                                    .padding(.bottom, 8)
                                Spacer()
                            }.padding(.bottom, 8)
                        }
                    }.padding(.vertical)
                }
            }
        }
    }.listStyle(GroupedListStyle())
        .navigationBarTitle(Text(passportTitle), displayMode: .inline)
}
}

Таким образом, очевидно, что «Text (item.passport [0] .passportTitle)» будет показывать первый элемент в массиве, но я хочу отобразить все passportTitlesи passportDates в верхнем массиве, а также передача информации в представление сведений с помощью NavigationLink.

1 Ответ

2 голосов
/ 04 ноября 2019

Исходя из вашего описания, вам нужна двухуровневая модель данных и иерархия представлений:

  1. Список событий (представленный структурой Passport)
  2. Списокместа для каждого события (представленные структурой Venue)

Ваша текущая модель данных состоит из трех уровней (Passports, содержащая Passport, содержащую Venue).

Еслимы удаляем постороннюю Passports структуру, мы можем очистить вашу статическую .all() функцию и PassportsView структуру.

extension Passport {
    static func all() -> [Passport] {
        return [
            Passport (
                id: 1001,
                passportPremium: false,
                passportActive: true,
                passportTitle : "Wine Festival",
                passportDates: "October 20 - November 3, 2020",
                venues: [
                    Venue (
                        title: "Bavaria Holiday Kitchen",
                        venueArea: "Germany Pavilion",
                        venueItems: [
                            venueItem (
                                title: "Potato Dumpling",
                                productDescription: "Potato Dumpling with Mushroom Sauce",
                                productPrice: 0.00,
                                productType: "Food",
                                newStatus: false,
                                diningPlan: false,
                                kidFriendly: true,
                                vegetarian: false,
                                glutenFree: false,
                                featuredProduct: false,
                                containsAlcohol: false
                            )
                    ])
            ])
        ]
    }
}

Вот обновленное представление:

struct PassportsView: View {

    var model = Passport.all()

    var body: some View {
        NavigationView {
            ForEach(self.model) { passport in
                NavigationLink (destination: PassportDetails(passportTitle: passport.passportTitle, venues: passport.venues, venueProd: []) ) {
                HStack {
                    VStack(alignment: .leading) {
                        Text(passport.passportTitle)
                            .fontWeight(.semibold)
                            .foregroundColor(Color.white)
                        Text(passport.passportDates)
                            .foregroundColor(Color.white)
                    }.frame(width: 400, height: 120)
                        .background(Color("wPurple"))
                        .cornerRadius(6)
                }
              }.padding(.horizontal)
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...