I am trying to create a Recpipe object (CoreData entity) and then pass that object to a ChildView after it's created. What's the best way to do this?
My first attempt was to create a @StateObject in the MainView and then pass that to ChildViews as an @ObservedObject, but this seems to only work great for objects that already exist. The @StateObject is a 'get only' property so I can't modify it based on the function return. Perhaps I don't really want to create a @StateObject in this circumstance?
struct MainView: View {
@State private var presentChildView: Bool = false
@StateObject private var recipe: Recipe = Recipe()
var body: some View {
VStack {
NavigationLink(destination: ChildView(recipe: recipe), isActive: $presentChildView) {
EmptyView()
}
Button("Action", action: {
recipe = functionThatReturnsRecipe()
presentChildView = true
})
}
}
}
struct ChildView: View {
@ObservedObject private var recipe: Recipe
var body: some View {
Text(recipe.title)
}
}
Normally you hold the object in @State
or even better inside a struct to hold all the ChildView
's related vars so it can be tested independently, e.g.
struct ChildViewConfig {
var recipe: Recipe?
var isPresented = false
mutating func present(viewContext: NSManagedObjectContext) {
recipe = Recipe(context: viewContext)
isPresented = true
}
// might have other save or dismiss mutating funcs here.
}
struct MainView: View {
@Environment(\.managedObjectContext) private var viewContext
@State private var config = ChildViewConfig()
var body: some View {
VStack {
Button("Present") {
config.present(context: viewContext)
}
}
.sheet(isPresented: $config.isPresented, onDismiss: nil) {
ChildView(recipe: config.recipe!)
}
}
}
struct ChildView: View {
@ObservedObject private var recipe: Recipe
var body: some View {
Text(recipe.title)
}
}
This answer to another question uses the more advanced .sheet(item:onDismiss)
that you may prefer because is designed for this use case of editing an item and allows for the use of a child context scratch pad because when setting the item to nil means the item.childContext
will be discarded if the editing in the sheet is cancelled.
Learn more about this @State
Config
struct pattern at 4:18 in Data Essentials in SwiftUI (WWDC 2020)