Post

Replies

Boosts

Views

Activity

macOS SwiftUI Commands and Core Data
Hi, I'm trying to create a new Core Data object from a Commands menu item in SwiftUI in macOS. TL:DR; how can I make a NavigationLink in the macOS Commands menu create a new Core Data object each time it is selected rather than once? I am using a NavigationLink to present a new window allowing the user to edit the new object. This works fine the first time; however on subsequent presentations the menu item is referencing the same item, not creating a new one. Here's my initial code: struct CommandMenu: Commands {   var context: NSManagedObjectContext   @CommandsBuilder var body: some Commands {     CommandMenu("Objects") {       NavigationLink(       destination: { ObjectEditor(object: object) .environment(\.managedObjectContext, context) },       label: { Text("New Object") }     )       .keyboardShortcut("o", modifiers: [.command, .shift])       Divider() // more commands here     }   } } I've tried a number of ways to try and make the NavigationLink lazy but I can't quite seem to get it right. Here's my most recent try: struct CommandMenu: Commands {   var context: NSManagedObjectContext   @CommandsBuilder var body: some Commands {     CommandMenu("Objects") {       LazyNavLink({ Object(context:context }) .environment(\.managedObjectContext, context) .keyboardShortcut("o", modifiers: [.command, .shift])       Divider() // more commands here     }   } } struct LazyNavLink: some View { @Environment(\.managedObjectContext) var context var object: () -> Object @ViewBuilder var body: some View { NavigationLink(     destination: { ObjectEditor(object: object()) .environment(\.managedObjectContext, context) },     label: { Text("New Object") }     ) } init(_ object: @escaping () -> Object) { self.object = object } } Unfortunately this still doesn't seem to work - the object is created at the point the view appears (i.e. at app launch). Both approaches seem to work but both behave in exactly the same way which is not what I was expecting. I was hoping the @escaping declaration would make the creation of the object only happen when the menu item was selected but this doesn't seem to be the case. Any pointers would be greatly appreciated!
1
0
785
Sep ’21
@SectionedFetchRequest using relationship as sectionIdentifier
As the title says I'm trying to use a to-one relationship as a sectionIdentifier in a @SectionedFetchRequest. The compiler is happy but there's a runtime crash: Could not cast value of type '_NSCoreDataTaggedObjectID' (0x146c0f750) to 'MyApp.ServiceCategory' (0x104c4b3a0). The fetch request: @SectionedFetchRequest(     sectionIdentifier: \Service.serviceCategory,     sortDescriptors: [       SortDescriptor(\Service.active, order: .reverse),       SortDescriptor(\Service.displayText)     ],     predicate: NSPredicate(format: "%K = %d", #keyPath(Service.active), true),     animation: .default   ) var sectionedServices: SectionedFetchResults<ServiceCategory?, Service> ... and the breaking runtime code: ForEach(sectionedServices /* here */) { section in Section(header: Text(section.id?.displayText ?? "")) { ForEach(section) { svc in Text(svc.displayText ?? "") } } } The request works if I switch out the sectionIdentifier for the active property (which is a Bool property rather than a relationship). It also works if I switch it out for displayText which is an optional String, so it seems to be a problem trying to section by a relationship rather than with it being an optional. The error suggests the request is returning a Core Data fault rather than an object but my attempts to somehow unwrap this haven't gone very far. Any thoughts would be greatly appreciated!
3
0
2.1k
Jun ’21