如何将数据从一个 SwiftUI 视图文件传递到另一个?

How do I pass data from one SwiftUI view file to another?

基本要点是我正在构建一个膳食计划应用程序。我是 Swift 和 SwiftUI 的新手,这是我的第一个项目,所以我可能犯了一个菜鸟错误大声笑基本上我想传递当前索引,这是一个数据当我点击相应的卡片时,一天的对象和它的膳食,到 DailyMealPlan 视图。当我将 currentDay 变量传递给视图时,我没有收到错误消息,但在第二个视图文件中,我不确定如何处理该数据。我不断收到“CurrentMealPlan 不在范围内”的错误消息。我了解范围的工作原理,我怀疑在将数据传递到第二个视图时我只是遗漏了一些东西。

ForEach 代码

ForEach(CurrentMealPlan.indices) { index in
                                    
  let currentDay = CurrentMealPlan[index]
    NavigationLink(
      destination: DailyMealPlan(DailyMealPlan: currentDay))
    {                                  
      MealPlanCard(
       Day: "\(CurrentMealPlan[index].DayTitle)",
       Breakfast: "\(CurrentMealPlan[index].Breakfast)",
       Lunch: "\(CurrentMealPlan[index].Lunch)",
       Dinner: "\(CurrentMealPlan[index].Dinner)"
      )
    }
}

DailyMealPlan 视图

struct DailyMealPlan: View {
    
    var DailyMealPlan: Day = CurrentMealPlan[index]
    
    var body: some View {
    
        ZStack {
            ScrollView {
                VStack {
                   
                    SingleMealCard(Meal: "Breakfast", CalCount: 500, MealInfo: "Meal info here")
                    
                    SingleMealCard(Meal: "Lunch", CalCount: 500, MealInfo: "Meal info here")
                    
                    SingleMealCard(Meal: "Dinner", CalCount: 500, MealInfo: "Meal info here")
                }
            }
        }
    }
}

当前膳食计划模型

struct Day: Hashable {
    var id: Int
    var Date: String
    var DayTitle: String
    var Breakfast: String
    var Lunch: String
    var Dinner: String
    
    
    init(id:Int=0,Date:String="",DayTitle:String="",Breakfast:String="",Lunch:String="",Dinner:String="") {
        self.id  = id
        self.Date = Date
        self.DayTitle = DayTitle
        self.Breakfast = Breakfast
        self.Lunch = Lunch
        self.Dinner = Dinner
    }
}

let CurrentMealPlan: [Day] = [
    Day(
        id: 0,
        DayTitle: "Sunday",
        Breakfast:"Oatmeal",
        Lunch: "Sandwich",
        Dinner: "Cheeseburger with Fries"
    )
]

让我们浏览一下您的代码。首先,您在父视图中声明了 CurrentMealPlan 数组。它可能看起来像这样:

@State var CurrentMealPlan = [Day]()

注意:作为 ,您应该小写 属性 名称,例如 var currentMealPlanvar dailyMealPlan。此外,不应该 DailyMealPlan 视图和 DailyMealPlan 属性 具有相同的名称...这非常令人困惑。

您的代码是正确的。然后,您遍历 CurrentMealPlan,并希望将每个元素传递给 DailyMealPlan 视图:

DailyMealPlan(DailyMealPlan: currentDay))

那也完全没问题。那么 CurrentMealPlan is not in scope 错误从何而来?就是这一行:

var DailyMealPlan: Day = CurrentMealPlan[index] /// NO!

请记住,您在父视图中声明了 CurrentMealPlan 而不是 DailyMealPlan 视图。这意味着 DailyMealPlan 视图无法访问 CurrentMealPlan.

但是,DailyMealPlan 视图 不需要 访问 CurrentMealPlan。回到父视图,您已经循环遍历 CurrentMealPlan 并将每个 currentDay 传递给 DailyMealPlan 视图。

因此,您需要做的就是定义 DailyMealPlan 属性:

的类型
struct DailyMealPlan: View {
   var DailyMealPlan: Day /// here!
   ...
}

这让编译器知道 var DailyMealPlan 接受了 Day.

我建议使用 MVVM 方法,每个屏幕视图都应该有自己的视图模型(应该是 class 扩展基本视图模型或协议),您在创建视图时传递它。

在你的情况下你应该:

protocol BaseViewModel {
}

class DailyMealPlanViewModel: BaseViewModel {
 @Published var day: Day

}

在上面我还添加了 day 作为 @Published 所以任何更改都会刷新视图,如果 day 永远不会改变您可以删除@Published。

在您看来:

struct DailyMealPlan: View {
 @StateObject var viewModel: DailyMealPlanViewModel
 ...
 ...

导航时:

NavigationLink(
      destination: DailyMealPlan(viewModel: DailyMealPlanViewModel(day: currentDay))
    ...
    ...