我想显示一份用餐类别列表(例如:意大利美食,中国美食等)及其各自的用餐子列表(例如:比萨->意大利美食列表的一部分,面条->中国美食列表的一部分) 。
我正在使用元组,但是在执行上述操作时遇到了麻烦。先感谢您。
这是我的模拟数据

// MOCK DATA FOR NOW!!
class FoodListViewModel {
    var meals: [Meal] = []
    var mealCategories = [(String, Meal)]()

    init() {
        // Initiate the model (Meal) in here
        fetchFood()
    }

    func fetchFood() {
        let meal1 = Meal(id: 1, name: "Fettucine", imageName: "linguine", rating: 4, description: "Delicious Fettucine Linguine with a side of basil", price: 20.10, category: "italian")
        let meal2 = Meal(id: 2, name: "Linguine", imageName: "linguine", rating: 4, description: "Delicious Fettucine Linguine with a side of basil", price: 20.10, category: "italian")
        let meal3 = Meal(id: 3, name: "Spaghetti", imageName: "linguine", rating: 4, description: "Delicious Fettucine Linguine with a side of basil", price: 20.10, category: "italian")
        let meal4 = Meal(id: 4, name: "Pesto", imageName: "linguine", rating: 4, description: "Delicious Fettucine Linguine with a side of basil", price: 20.10, category: "italian")
        let meal5 = Meal(id: 5, name: "Noodles", imageName: "linguine", rating: 4, description: "Delicious Chao Ming with a side of basil", price: 20.10, category: "chinese")
        let meal6 = Meal(id: 6, name: "Spicy Noodles", imageName: "linguine", rating: 4, description: "Delicious Chao Ming with a side of basil", price: 20.10, category: "chinese")
        let meal7 = Meal(id: 7, name: "Tacos", imageName: "linguine", rating: 4, description: "Delicious Chao Ming with a side of basil", price: 20.10, category: "mexican")


        meals.append(meal1)
        meals.append(meal2)
        meals.append(meal3)
        meals.append(meal4)
        meals.append(meal5)
        meals.append(meal6)
        meals.append(meal7)

        mealCategories.append(("italian", meal1))
        mealCategories.append(("italian", meal2))
        mealCategories.append(("italian", meal3))
        mealCategories.append(("italian", meal4))
        mealCategories.append(("chinese", meal5))
        mealCategories.append(("mexican", meal6))
    }
}
进餐班
struct Meal: Identifiable {
    var id: Int
    var name: String
    var imageName: String
    var rating: Int
    var description: String
    var price: Double
    var category: String

    init(id: Int, name: String, imageName: String, rating: Int, description: String, price: Double, category: String) {
        self.id = id
        self.name = name
        self.imageName = imageName
        self.rating = rating
        self.description = description
        self.price = price
        self.category = category
    }
}
这是我想如何显示它的粗略概念
struct FoodListView: View {
    var viewModel: FoodListViewModel

    var body: some View {
        NavigationView {
            VStack {
                ForEach(viewModel.mealCategories.key) { category in
                    Text("\(category)")
                        // Display list of meals (values) associated with this category (key) here
                        meals //
                }
            }
        }
    }
}

extension FoodListView {
    var meals: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 20) {
                ForEach(viewModel.mealCategories.value) { meal in
                        NavigationLink(destination: FoodDetailView(viewModel: FoodDetailViewModel(meal: meal))) {
                            FoodListRowView(viewModel: FoodListRowViewModel(meal: meal))
                        }.buttonStyle(PlainButtonStyle())
                }
            }
        }
    }
}
这是FoodListRowView的代码
struct FoodListRowView: View {
    @ObservedObject var viewModel: FoodListRowViewModel

    var body: some View {
        ZStack {
            Rectangle()
                .fill(Color(red: 237/255, green: 239/255, blue: 241/255))
                .frame(width: 250, height: 320, alignment: .center)
                .cornerRadius(8)
                .shadow(color: .gray, radius: 5, x: 0, y: -0.01)

            VStack() {
                Image("\(self.viewModel.meal.imageName)")
                    .resizable()
                    .frame(width: 250, height: 220, alignment: .top)


                RatingView(rating: .constant(4))

                Text("\(self.viewModel.meal.name)")
                    .bold()
                    .font(.largeTitle)
                Text("\(self.viewModel.meal.price)$")

            }.frame(width: 250, height: 320, alignment: .top)
        }
    }
}
这是FoodListRowViewModel的代码
class FoodListRowViewModel: ObservableObject {
    var meal: Meal

    init(meal: Meal) {
        self.meal = meal
    }
}

最佳答案

首先,您可以将模型从元组更改为字典。这样,您的饭菜就可以轻松地按类别分组。

var mealCategories = [String: [Meal]]()
另外,由于您的Meal结构已经具有category字段,因此您可以循环填充mealCategories:
meals.forEach { meal in
    mealCategories[meal.category, default: []].append(meal)
}
请注意,由于Swift中的字典是无序的,因此您可能需要对其进行排序。
struct FoodListView: View {
    ...
    var body: some View {
        let categories = Array(viewModel.mealCategories.keys).sorted() // sorted list of categories
        return NavigationView {
            ScrollView(.vertical) {
                ForEach(categories, id: \.self) { category in
                    VStack {
                        Text("\(category)")
                        self.categoryView(meals: self.viewModel.mealCategories[category, default: []])
                    }
                }
            }
        }
    }
}
category视图:
extension FoodListView {
    func categoryView(meals: [Meal]) -> some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 20) {
                ForEach(meals, id: \.id) { meal in
                    NavigationLink(destination: Text("meal")) {
                        FoodListRowView(viewModel: FoodListRowViewModel(meal: meal))
                            .padding()
                    }
                    .buttonStyle(PlainButtonStyle())
                }
            }
        }
    }
}

07-24 09:45
查看更多