10

There is a similar question in stack overflow already but it doesn't work for me.

There is a use case in my application where I have to observe the database changes to perform some operation. To receive updates I subscribed to NSManagedObjectContextObjectsDidChange notification (for ViewContext) and also I turned on automaticallyMergesChangesFromParent.

But, if I update or delete the object on some other context (using newBackgroundContext()), I don’t receive object did change notification but it’s working perfectly for inserting new objects.

Can you someone please guide me why it does work only for insert, not for update and delete even after enabling automaticallyMergesChangesFromParent? if it's the actual behavior, Is there any other way to solve my use case?

The documentation (in NSManagedObjectContext.h) for .automaticallyMergesChangesFromParent says:

Whether the context automatically merges changes saved to its coordinator or parent context. Setting this property to YES when the context is pinned to a non-current query generation is not supported.

What I tried

  • I debugged by testing if updated/deleted objects are already registered in the view context. Yes, those are already registered.
  • I tested the same thing using NSFetchResultController it’s working good but unfortunately, I can’t use NSFetchResultController as I use a custom view to represent the data
  • Also, I tried creating a new privateQueueConcurrencyType context and setting viewContext as a parent and it surprisingly started working so the issue is only while using newBackgroundContext() but as per document it should work properly as both are using same NSPersistentStoreCoordinator

Thanks in advance!

thavasidurai
  • 1,972
  • 1
  • 26
  • 51
  • 1
    Why are you using the notification? Can you use a fetchedResultsController to monitor the context? – Jon Rose Jul 08 '19 at 05:37
  • In my use case, I can't use FRC so I decided to go with notification please refer the link below. https://stackoverflow.com/questions/55686097/how-to-add-additional-objects-with-fetch-result-controller-fetched-objects-list – thavasidurai Jul 09 '19 at 09:41
  • BTW if you think it would work well in FRC then why it doesn't in the notifications I really believe FRC also performs observing same notifications behind the scene. – thavasidurai Jul 09 '19 at 09:48
  • 1
    1) suspect the issue is that the objects aren't faulted in the context you are merging the changes into (I am not sure so I am not making this an answer). 2) I read your other question. You should still use an FRC. I always use FRCS. i use FRC even for just a single object. (maybe use 2?). good luck! – Jon Rose Jul 09 '19 at 09:56
  • I tried out using FRC in a sample project it's working good but in my use case I will show the data in 3 different UI among them only one is a table view where I can use FRC it would solve the issue what about remaining two? where I fetch the data using fetch request and show them in a custom view here we don't need to use FRC how can we solve it? – thavasidurai Jul 12 '19 at 11:16
  • always use FRC. user multiple FRC. use as many as need as often as you need. they are amazing! use multiple for one table view if necessary. FRCs work great with tableview and collectionView using the same indexPath, but they can interface any way you want. – Jon Rose Jul 13 '19 at 18:58

2 Answers2

4

"I can’t use NSFetchResultController as I use a custom view to represent the data" not true, the FRC can and should be used with any view (that shows multiple objects).

As for why you are not receiving the NSManagedObjectContextObjectsDidChange in the case of updates (which come in as refreshed) or deletes I have a few theories:

  1. Maybe not properly called _persistentContainer.viewContext.automaticallyMergesChangesFromParent = YES; because that causes exactly the situation you describe (receiving inserts but not updates or deletes). It should be done in the persistentContainer custom getter in your app delegate after loadPersistentStoresWithCompletionHandler (and not inside the block).

  2. Perhaps not using performBlock with your background context.

  3. Possibly not registered for the did change notification correctly.

  4. (In light of new information) Not retaining the fetched objects.

If you would like to share some code we can help you track down the bug.

malhal
  • 26,330
  • 7
  • 115
  • 133
  • Thanks for the response. I checked my code and all three you mentioned are perfectly implemented so that would not be a problem. I debugged before updating a managed object whether it is already registered into the view context or not but the result is NO which means view context somewhere losing its objects. I am fetching the objects using view context and converting them as custom objects to use it in UI. Here fetched managed objects scope is limited to particular fetch method. Do you think it would be a problem? If fetched objects deallocated, will context lose the registered objects? – thavasidurai Jul 22 '19 at 10:27
  • 1
    Yes that's the problem. You need to retain the objects fetched, e.g. in a strong array property. You can create a custom property on the NSManagedObject subclass to format the data from the object into what you want to use in your UI. You can also use KVO Registering Dependent Keys to be notified when values that make up your UI display property change. – malhal Jul 22 '19 at 14:59
0

Probably not totally an answer but just some thoughts and suggestions that are not well enough structured for a comment.

It could be related to the viewContext not retaining the objects, rather just faults because they weren't being used anymore directly (such as in a tableview). There would be retainsRegisteredObjects for that.

Also, did you ever access the property that has been changed in the viewContext? That could also be an issue, that it wont recognize a change on an object that never got read.

I strongly recommend using one or multiple FRC for those cases, they bridge the notifications for you and provide a cleaner interface. It does not matter if you have a custom view, just implement the FRCDelegate methods and you will be fine. I think it could be easier to help you if you ask another question why you cannot use FRC (where are the problems?) with your custom view.

MartinM
  • 832
  • 6
  • 12
  • Thanks for the response! 1) I tried enabling retainsRegisteredObjects it notifies the first one update but it fails to notify the consecutive updates 2) No, I did not access the property that has been changed in the view context 3) Yes, some where I read it like using FRC is not recommended to use if we don’t use table view/collection view any way I solved it by creating new private queue concurrency type context and setting view context as parent but I would really like to know why it does not work in my first approach as per the doc it should work well – thavasidurai Jul 17 '19 at 07:25
  • Maybe you could try accessing that property first as described in 2.) that is supposed to be changed? Maybe that helps @thavasidurai – MartinM Jul 17 '19 at 10:23