Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deleting Objects Fails to Fire Collection Change Notification via LinkingObjects Relationship #8388

Open
bdkjones opened this issue Oct 4, 2023 · 3 comments

Comments

@bdkjones
Copy link

bdkjones commented Oct 4, 2023

How frequently does the bug occur?

Always

Description

This is complex. Here are the (truncated) Objects involved:

final class SheetCue: Object
{
    @Persisted(primaryKey: true) var _id: UUID
    @Persisted var associatedMasterCue: MasterCue? = nil
}
final class MasterCue: Object
{
    @Persisted(primaryKey: true) var _id: UUID
    
    @Persisted var associatedProjectScopedCueFlags: LinkingObjects<ProjectScopedCueFlag> = LinkingObjects(fromType: ProjectScopedCueFlag.self, property: "associatedMasterCue")

    @Persisted var associatedSheetCues: LinkingObjects<SheetCue> = LinkingObjects(fromType: SheetCue.self, property: "associatedMasterCue")
}
final class ProjectScopedCueFlag: Object
{
    @Persisted(primaryKey: true) var _id: UUID
    @Persisted var isEnabled: Bool = false
    @Persisted var associatedMasterCue: MasterCue?
    
}

I create some MasterCue and SheetCue Objects. The SheetCue objects are displayed in an NSTableView and I fetch them into a Results<SheetCue> live collection. Now, when the .associatedMasterCue.associatedProjectScopedCueFlags property changes for any SheetCue, I need to reload that row of the table and draw a "flag" icon to indicate that this Object has a problem the user should address.

So, I use a collection change handler:

// Assume "cues" is the Results<SheetCue> live collection and `cuesRealmToken` is an iVar.
cuesRealmToken = cues?.observe(keyPaths: [\.associatedMasterCue?.associatedProjectScopedCueFlags]) { [weak self] (changes: RealmCollectionChange) in { 
   ... 
}

This works perfectly if:

  1. A ProjectScopedCueFlag is added to the realm and has its associatedMasterCue property set.

  2. I modify the isEnabled property of any ProjectScopedCueFlag in the observed LinkingObjects<>

However, this notifier does NOT fire if:

  1. I delete the ProjectScopedCueFlag Object from the Realm.

  2. I set the associatedMasterCue property of one of the flag Objects to nil (thus removing it from the LinkingObjects<>)

My project uses Atlas Device Sync and I can see, after I make changes, that the database is exactly as it should be: the relationships on all Objects are set correctly. The changes do occur, the deletions just don't fire the notifications.

My Workaround

To trigger the notification, I first loop over all the flag objects that I am going to delete and change a property. (My UI draws differently based on the value of this property.) Changing that property fires the notification. Then, I go back and delete the flag objects in a second write transaction. Obviously, that's not ideal:

Screenshot 2023-10-04 at 01 47 06

Related Issue Search

I found #7495, which seems related. It was marked as fixed and mentioned that LinkingObjects were only handling insertions.

Stacktrace & log output

N/A

Can you reproduce the bug?

Always

Reproduction Steps

See Above.

Version

10.42.4

What Atlas Services are you using?

Both Atlas Device Sync and Atlas App Services

Are you using encryption?

No

Platform OS and version(s)

macOS Sonoma 14.0

Build environment

Xcode version: 15.0
Dependency manager and version: SPM

@bdkjones
Copy link
Author

bdkjones commented Oct 4, 2023

I realize the object naming is more cumbersome than foo and bar, but I wanted to match the screenshot of my actual code.

MasterCue Objects model sound clips. They have two dozen properties like artist, title, album, etc.

SheetCue Objects model one use of a sound clip in an audio timeline. (We might use the same clip 12 times in our project's timeline at different points, so SheetCue tracks when those points occur and then links to the backing MasterCue so we only keep one copy of all the metadata values.)

@Jaycyn
Copy link

Jaycyn commented Oct 5, 2023

I can duplicate this issue as well. One thing to note though; Formally, LinkingObject properties should be defined

@Persisted(originProperty: "associatedMasterCue") var associatedProjectScopedCueFlags: LinkingObjects<ProjectScopedCueFlag>

instead of

@Persisted var associatedProjectScopedCueFlags: LinkingObjects<ProjectScopedCueFlag> = LinkingObjects(fromType: ProjectScopedCueFlag.self, property: "associatedMasterCue")

It didn't affect this our testing either way.

@luciengaitskell
Copy link

I'm also having this problem. From my testing, the notification seems to be fired when creating a back-linked object but not when deleting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants