how can I discern which SwiftData object trigger the .NSManagedObjectContextDidSave notification ?

Presently, I am encountering an issue with SwiftData. For instance, I have a SwiftData class Ledger that encompasses an array of SingleTransaction, which is also a SwiftData class.

Here is the question: when I save a Ledger, how can I discern that the .NSManagedObjectContextDidSave notification was triggered by saving the Ledger and not by saving a SingleTransaction? This distinction is crucial to circumvent unnecessary updates. I attempted the following syntax, but Xcode indicates that Cast from NSManagedObject to unrelated type Ledger always fails.

List {...}
.onReceive(
   NotificationCenter
   	.default
        .publisher(for: .NSManagedObjectContextDidSave)
        .receive(on: DispatchQueue.main), 
  perform: { notification in
      if let userInfo = notification.userInfo,
         let updatedObjects = userInfo[NSUpdatedObjectsKey] as? Set<NSManagedObject> {
             if updatedObjects.contains(where: { $0 is Ledger }) {
             	fetchLedgers()
             }
         }
     }
)

What can I do?

Answered by DTS Engineer in 808175022

"This distinction is crucial to circumvent unnecessary updates."

Yeah, avoiding unnecessary UI updates is important. To figure out what change should trigger an update, you can look into the details of the changes provided in the SwiftData history, which was introduced in WWDC2024.

For more information about SwiftData history, please see the Track model changes with SwiftData history session. For a workable sample, see the Detect relevant changes by consuming the SwiftData history section of the Adopting SwiftData for a Core Data app sample.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Accepted Answer

"This distinction is crucial to circumvent unnecessary updates."

Yeah, avoiding unnecessary UI updates is important. To figure out what change should trigger an update, you can look into the details of the changes provided in the SwiftData history, which was introduced in WWDC2024.

For more information about SwiftData history, please see the Track model changes with SwiftData history session. For a workable sample, see the Detect relevant changes by consuming the SwiftData history section of the Adopting SwiftData for a Core Data app sample.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

If we have to target iOS17, what would be the solution here?

I don't see any good solution for iOS 17 unfortunately.

Some folks discussed how to convert the permanent objectID of a Core Data managed object to a SwiftData PersistentIdentifier (and find the associated SwiftData model from there), but the relationship between NSManagedObjectID and PersistentIdentifier is not publicly documented, and so is not something I'd talk about.

Another piece worth mentioning: I just confirmed that ModelContext.didSave now works on iOS 18 (22A3364). If you are using .NSManagedObjectContextDidSave, you can replace it with ModelContext.didSave and grab the SwiftData changes from the notification's user info dictionary. With that, you don't need to look into the SwiftData history.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

how can I discern which SwiftData object trigger the .NSManagedObjectContextDidSave notification ?
 
 
Q