TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

Recipe: compile or runtime error depending on placement of recipe declaration; how to fix?

Forums > SwiftUI

I am working on an app modeled after Paul's UltimatePortfolio. In the file AddRecipeView, I want to create a new recipe, with all its subordinate attributes and ingredients. This file/struct is called from ContentView.swift just as in UltimatePortfolio, as:

import SwiftUI

struct ContentView: View {
    @SceneStorage("selectedView") var selectedView: String?

    var body: some View {
        TabView(selection: $selectedView) {
            AddRecipeView()
                .tag(AddRecipeView.tag)
                .tabItem {
                    Image(systemName: "tray.and.arrow.down")
                    Text("Add Recipe")
                }
        }
    }
}

My Recipe and Ingredient classes are defined in Main.xcdatamodeld, with Recipe having an attribute of name, of type String. I have stripped out all the additional code for Recipe attributes and Ingredient and its attributes.

There is a an extension on Recipe for name, in the file Recipe-CoreDataHelpers.swift, as:

extension Recipe {

    var recipeName: String {
        name ?? ""                  // runtime error here!
    }
}

I get a compile error in AddRecipeView: ‘Cannot find “recipe” in scope’ on the line “addIngredient(to: recipe)“, when the line 'let recipe = Recipe()' is the first line of init(). And, if I move the line 'let recipe = Recipe()' above init(), I get a runtime error on the line 'name ?? "" ' in Recipe-CoreDataHelpers.swift. Apparently, something is wrong with 'recipe', but I can't figure out what. Can you please help with whatever I am missing? TIA, Bill

import SwiftUI

struct AddRecipeView: View {

    @Environment(\.managedObjectContext) var managedObjectContext
    @EnvironmentObject var dataController: DataController
    @Environment(\.presentationMode) var presentationMode

    @State private var name: String

    static let tag: String? = "AddRecipeView"

    init() {
        let recipe = Recipe()
        _name = State(wrappedValue: recipe.recipeName)
    }

    var body: some View {
        Form {
            Section(header: Text(“Basic settings”)) {
                TextField(“Recipe Name”, text: $name.onChange(update))
            }

            Button {
                addIngredient(to: recipe)                // compile error here!
            } label: {
                Label(“Add New Ingredient”, systemImage: “plus”)
            }
        }
        .navigationTitle(“Add Ingredient”)
        .onDisappear(perform: dataController.save)
    }

    func addIngredient(to recipe: Recipe) {
        withAnimation {
            let ingredient = Ingredient(context: managedObjectContext)
            ingredient.recipe = recipe
            dataController.save()
        }
    }

    func update() {
        recipe.name = name
    }

    func delete() {
        presentationMode.wrappedValue.dismiss()
    }
}

2      

Hacking with Swift is sponsored by Blaze.

SPONSORED Still waiting on your CI build? Speed it up ~3x with Blaze - change one line, pay less, keep your existing GitHub workflows. First 25 HWS readers to use code HACKING at checkout get 50% off the first year. Try it now for free!

Reserve your spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.