best practices - NSManagedObjectContextObjectsDidChangeNotification in iOS
Asked Answered
P

2

10

I am writing my first comprehensive app using Core Data, and I want to see what the best way to keep track of various object changes / updates / deletes is. For example, I have a Notes entity and a Location entity, and a one-to-one relationship between them, the idea being that each note could have its location tagged. I then have a UITableView with a fetchedResultsController driving the list of notes (where you can add new notes and attach a date and location to them), but then I have 2 other view controllers, one with a map view and one with a calendar view. The map view fetches all the locations in Location and displays them on a map. The calendar view basically gets all the data from Notes again and just shows it in a calendar view. How should I keep track of changes to Notes and Location in my calendar and map view? It's easy to load them up once in viewDidLoad, but how should I keep track of all the changes, so that when the user revisits the mapview (for e.g.) he/she sees the latest data as well.

The one way I've deciphered is to listen for notifications in NSManagedObjectContextObjectsDidChangeNotification, in both the maps view and the calendar view. This seems to return all the inserted, deleted and updated objects from a managed context, each time there's a save. I could then go through these objects and see if I need to update my view. This is how I'm thinking of doing it:

In MapViewController viewDidLoad:

[[NSNotificationCenter defaultCenter]
    addObserver: self
    selector: @selector(objectChangedNotificationReceived:)
    name: NSManagedObjectContextObjectsDidChangeNotification
    object: context];

Then:

- (void) objectChangedNotificationReceived: (NSNotification *) notification
{
    NSArray* insertedObjects = [[notification userInfo]
                                objectForKey:NSInsertedObjectsKey] ;
    NSArray* deletedObjects = [[notification userInfo]
                               objectForKey:NSDeletedObjectsKey] ;
    NSArray* updatedObjects = [[notification userInfo]
                               objectForKey:NSUpdatedObjectsKey] ;
    NSLog(@"insertObjects: %@", [insertedObjects description]);
    NSLog(@"deletedObjects: %@", [deletedObjects description]);
    NSLog(@"updatedObjects: %@", [updatedObjects description]);

    for (NSManagedObject *obj in insertedObjects) {
        if ([obj class] == [Location class]) {
            NSLog(@"adding a new location");
            Location *locationObj = (Location *) obj;
            [self.mapview addAnnotation: locationObj];
        }
    }
}

Does this seem about right? It seems like a lot of redundant code to put into each view controller, especially if I'm interested in more than one NSManagedObject. Is there some other technique that I'm missing?

Perigee answered 20/7, 2011 at 5:54 Comment(1)
Doesn't NSInsertedObjectsKey returns NSSet rather than NSArray?Scofield
T
3

NSFetchedResultsController seems to fit your requirement. It will efficiently manage the data handling from the Core Data. You reuse the same fetch request for both of your calendar view controller and map view controller.

Tarrant answered 3/4, 2012 at 2:25 Comment(2)
I did end up using NSFetchedResultsController, even though my views didn't have a tableview associated with them, and it works like a charm!Perigee
@ZS Obviously, NSFetchedResultsController has NOT to be related to tableView.Antiworld
O
2

Why can't you just fetch the latest data directly from CoreData on the viewWillLoad or viewDidLoad method. This will ensure that you have the latest objects.

Seems like that would be more modular and cleaner.

Operational answered 3/4, 2012 at 1:51 Comment(1)
Too much overhead. Creating a FRC that listens to changes for you is the way to go .Perigee

© 2022 - 2024 — McMap. All rights reserved.