My app currently uses a NavigationLink
to open a view like this:
LazyVGrid(columns: gridLayout, spacing: 10) {
ForEach(Array(person.project! as! Set<Project>).sorted { $0.date! > $1.date! }, id: \.self) { (project: Project) in
NavigationLink(destination: ProjectDetailView(project: project, rootIsActive: self.$isActive)) {
Image(uiImage: UIImage(data: project.image1 ?? self.projectImage1)! )
...
However to improve the flow of the UI, I'd like to use a Sheet
instead of NavigationLink
to show ProjectDetailView
So I changed it like this:
LazyVGrid(columns: gridLayout, spacing: 10) {
ForEach(Array(person.project! as! Set<Project>).sorted { $0.date! > $1.date! }, id: \.self) { (project: Project) in
Image(uiImage: UIImage(data: project.image1 ?? self.projectImage1)! )
.onTapGesture(count: 1) { sheet = .imageTap(project) }
}
where imageTap
is added to my sheet enum at the top:
enum Sheet { case imageTap(Project) }
@State var sheet: Sheet? = nil
and my sheet modifier passes the objectID
of project
to the view:
.sheet(using: $sheet) { sheet in
switch sheet {
case .imageTap:
ProjectDetailView(id: project.objectID, in: viewContext)
In my ProjectDetailView I've defined my @ObservedObject
and initialized like this:
@Environment(\.managedObjectContext) private var viewContext
@ObservedObject var project: Project
init(id objectID: NSManagedObjectID, in context: NSManagedObjectContext) {
if let project = try? context.existingObject(with: objectID) as? Project {
self.project = project
self._image1 = State(wrappedValue: project.image1!)
self._image2 = State(wrappedValue: project.image2 ?? self.image2)
self._image3 = State(wrappedValue: project.image3 ?? self.image3)
self._image4 = State(wrappedValue: project.image4 ?? self.image4)
self._fav = State(wrappedValue: project.favorite)
} else {
self.project = Project(context: context)
try? context.save()
}
}
I'm expecting the objectID
to be passed into this view when I invoke the onTapGesture
on the image. However Xcode errors at this point with
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'nil is not a valid object ID'
I'm using this same method of passing objectID
to edit a Person entity (my app has two core data entities: Person and Project), though it doesn't use a ForEach.
It's just a .toolbar
button and it works as expected. So I had it print the person.ObjectID
and it looked like this:
0x8ae3a33c4ba2adf9 <x-coredata://468DD15D-71D2-4990-BD8B-01CAA9786420/Person/p5>
So I went and had it print the project.ObjectID
upon tapping the image, and it prints a similar string that looks valid to me:
0x8ae3a33c49e2add9 <x-coredata://468DD15D-71D2-4990-BD8B-01CAA9786420/Project/p23>
So I'm pretty confused as to why ProjectDetailView is receiving a nil
value when printing the objectID
upon invoking imageTap
produces a valid looking objectID
Any ideas? Thanks!!
CodePudding user response:
(As discussed in the comments above)
I'm not sure which instance of project you're referencing on the line ProjectDetailView(id: project.objectID, in: viewContext)
or in what scope it exists, but instead, you should be using the associated value in the enum that you set when you do sheet = .imageTap(project)
.
In that case, the prior line should be: case let .imageTap(project):
instead of case .imageTap
.