Hey,
So I am tryingn to get my recipeView to change based on the navigation link selection on the home page-- for example, selecting vegan should load the Vegan recipes from the vegan api link, the breakfast should load only the breakfast api link. But the problem I am having is switching the recipe list view api based on their selection in the contentView from the navigaiton links.
Content View
import SwiftUI
struct ContentView: View {
let items = ["Vegan", "Breakfast", "Lunch", "Dinner"]
let rows: [GridItem] = [GridItem(.fixed(150))]
@StateObject var navSelected = NavSelection()
var body: some View {
NavigationView {
ScrollView {
ScrollView(.horizontal, showsIndicators: false) {
LazyHGrid(rows: rows, alignment: .center) {
ForEach(items, id: \.self) { item in
NavigationLink {
RecipeList(navSelection: navSelected)
} label: {
VStack(alignment: .leading, spacing: 0) {
Image("navigation/\(item)") // image view here
.frame(width: 103, height: 101)
.cornerRadius(10)
.foregroundColor(.gray)
Text(item)
}
}
}
}
.frame(height: 150)
}
.padding(.horizontal)
}
}
.preferredColorScheme(.dark)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Recipes API Call
import SwiftUI
struct Recipes: Identifiable, Codable {
let id: Int
let name: String
let creator: String
let serves: Int
let ingredients: [Ingredient]
let methods: [Method]
let imageURL: URL
enum CodingKeys: String, CodingKey {
case id, name, creator, serves, ingredients
case methods = "method"
case imageURL = "imageurl"
}
}
struct Ingredient: Codable {
let name: String
let quantity: Double
let measurement: String
}
struct Method: Codable {
let step: Int
let text: String
}
let veganS3 = "https://recipesstore.s3.eu-west-2.amazonaws.com/vegan.json"
let breakfastS3 = "https://recipesstore.s3.eu-west-2.amazonaws.com/breakfast.json"
let lunchDinnerS3 = "https://recipesstore.s3.eu-west-2.amazonaws.com/lunchdinner.json"
var s3API = ""
@MainActor
class RecipeAPI: ObservableObject {
@Published var Recipe: [Recipes] = []
func fetchRecipes() async {
let apiURL = URL(string: s3API)!
// Use Enum switch case for URL depedning on what is selected on content View.
do {
let (data, _) = try await URLSession.shared.data(from: apiURL)
let decoder = JSONDecoder()
Recipe = try decoder.decode([Recipes].self, from: data)
} catch {
print(error)
}
}
}
class NavSelection: ObservableObject{
@Published var Selected = [String]()
func switchAPI(){
if Selected == ["Vegan"]{
s3API = veganS3
}else if Selected == ["Breakfast"]{
s3API = breakfastS3
}else if Selected == ["Lunch"] {
s3API = lunchDinnerS3
}else if Selected == ["Dinner"] {
s3API = lunchDinnerS3
}
}
}
RecipeListView
import SwiftUI
struct RecipeList: View {
@StateObject var Api = RecipeAPI()
@ObservedObject var navSelection: NavSelection
var body: some View {
NavigationView {
VStack{
Image("Rectangle")
.frame(height: 244)
List{
HStack{
Text(navSelection.Selected)
.font(.title)
.fontWeight(.heavy)
}
ForEach(Api.Recipe){ recipe in
NavigationLink {
Text(recipe.name)
} label: {
AsyncImage(url: URL(string: "\(recipe.imageURL)")) { image in
image.resizable()
} placeholder: {
Color.gray
}
.frame(width: 130, height: 81)
VStack(alignment: .leading){
Text(recipe.name)
.font(.headline)
HStack{
Text(recipe.creator)
.font(.subheadline)
}
}
}
}
}
.task {
await Api.fetchRecipes()
}
}
.ignoresSafeArea(edges: .top)
}
.preferredColorScheme(.dark)
}
}
struct VeganRecipesList_Previews: PreviewProvider {
static var previews: some View {
RecipeList()
}
}
I've proably overcomplicated this alot or messed up somewhere. Please help.
Best,
imran