Reputation: 33
The basic gist is I'm building a meal planner app. I'm new to Swift and SwiftUI and this is my first project so I'm probably making a noob mistake lol Basically I want to pass the current index, which is a data object for a day and it's meals, to the DailyMealPlan view when I tap on the corresponding card. I don't get an error when I pass the currentDay variable to the view, but inside the second view file I'm not sure how I handle that data. I keep getting an error that "CurrentMealPlan is not in scope". I understand how scope works and I suspect I'm just missing something when it comes to passing the data into the second view.
ForEach code
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 view
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")
}
}
}
}
}
CurrentMealPlan model
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"
)
]
Upvotes: 0
Views: 1241
Reputation: 132
I suggest using a MVVM approach, each screen view should have it's own view model (which should be a class extending a base view model or protocol) which you pass when you create the view.
In your case you should have:
protocol BaseViewModel {
}
class DailyMealPlanViewModel: BaseViewModel {
@Published var day: Day
}
in the above I also added day as @Published so any changes on that will refresh the view, if the day never changes you can remove @Published.
in your view:
struct DailyMealPlan: View {
@StateObject var viewModel: DailyMealPlanViewModel
...
...
And when navigating:
NavigationLink(
destination: DailyMealPlan(viewModel: DailyMealPlanViewModel(day: currentDay))
...
...
Upvotes: 0
Reputation: 30268
Let's walk through your code. First, you declared the CurrentMealPlan
array inside the parent view. It probably looks something like this:
@State var CurrentMealPlan = [Day]()
Note: As jnpdx commented, you should lowercase property names like var currentMealPlan
and var dailyMealPlan
. Also, you should not have the same name for the DailyMealPlan
view and the DailyMealPlan
property... it's extremely confusing.
Your code is correct. Then, you loop over CurrentMealPlan
, and want to pass each element over to the DailyMealPlan
view:
DailyMealPlan(DailyMealPlan: currentDay))
That's also completely fine. So where does the CurrentMealPlan is not in scope
error come from? It's this line:
var DailyMealPlan: Day = CurrentMealPlan[index] /// NO!
Remember, you declared CurrentMealPlan
inside the parent view, not the DailyMealPlan
view. That means the DailyMealPlan
view can't access CurrentMealPlan
.
However, the DailyMealPlan
view does not need to access CurrentMealPlan
. Back in the parent view, you're already looping through CurrentMealPlan
and passing in each currentDay
over to the DailyMealPlan
view.
So, all you need to do is define the type of the DailyMealPlan
property:
struct DailyMealPlan: View {
var DailyMealPlan: Day /// here!
...
}
This lets the compiler know that var DailyMealPlan
takes in a Day
.
Upvotes: 3