Table() structure selection takes Object.ID but how to obtain reference to NSManagedObject from this ID

I am using the new SwiftUI Table() structure available for macOS.

This structure takes a selection of multiple rows as a Set<Object.ID> and can be stored in a state property wrapper like so...

@State private var selectedPeople = Set<Person.ID>()

(per the example in the Apple documentation)

Table() doesn't take any other type of identifier (that I am aware of), so I am constrained to use the ObjectIdentifier unique identifier.

I am using Table() to present a list of NSManagedObjects.

These NSManagedObjects are sourced from a Core Data Entity relationship property, in this case via a @FetchRequest.

I want to be able to add new instances of the entity and also delete existing instances of the entity. I have worked out how to add a new instance - this is relatively easy.

What I am struggling to work out is how to delete an NSManagedObject from the Table() by using the Object.ID that is used to track row selection.

I have attempted this...

    @State private var tableSelection = Set<Action.ID>()
    ...
    for actionID in tableSelection {
        let context = event.managedObjectContext
        let actionToDelete = context?.object(with: actionID)
        print(actionToDelete)
        context?.delete(actionToDelete)
    }

but of course I have a type mismatch here and the compiler complains...

Cannot convert value of type 'Action.ID' (aka 'ObjectIdentifier') to expected argument type 'NSManagedObjectID'

So how I do grab a reference to the selected NSManagedObject from the set of Action.ID?

Replies

Here is my answer...

Two alternatives:

  1. Iterate over the tableSelection, then filter the NSSet where the entity.id equals the tableSelection ID (there will be only one), then iterate over the resulting array of NSManagedObject.
  2. Filter the NSSet where the entity.id is in the tableSelection, then iterate over the resulting array of NSManagedObject.

Example for option 1:

@State private var tableSelection = Set<Action.ID>()
...
if let eventActions = event.actions {
    for actionID in tableSelection {
        let eventActionsSelected = eventActions.filter { ($0 as! Action).id == actionID } as! [NSManagedObject]
        for action in eventActionsSelected {
            // perform some action... e.g.
            context?.delete(action)
        }
    }
}

Example for option 2:

@State private var tableSelection = Set<Action.ID>()
...
if let eventActions = event.actions {
    let eventActionsSelected = eventActions.filter { tableSelection.contains(($0 as! Action).id) } as! [NSManagedObject]
    for action in eventActionsSelected {
        // perform some action... e.g.
        context?.delete(action)
    }
}

I prefer Option 2. While there is a bit too much force downcasting for my liking, at least both options work and from here I can improve.