I'm missing something in my logic when trying to sync web service data with local store and I need your help. This is what I've got:
I have one NSArray
of NSDictionaries
describing each event object (downloaded from web), which I sort by event id. Then I fetch local store using IN predicate and also sort it by event id. Then I try to iterate and match the ids and if they match, i update record and if they don't match i create new NSManagedObject
. It works fine if the newly downloaded event object has a greater eventID than last eventID in local store, but if the eventID from web service is smaller than the one in local store then it INSERTS ALL OBJECTS, no matter if they exist or not and that exactly is my problem.
So in other words, if a new record is at the beginning of sorted array it will add every object, but if it is at the end of sorted array it will update all except the new one. I need it to create the new one and update old ones.
Here's some code:
The function with the logic where I believe I'm missing something:
- (void)findOrCreateObject:(NSArray*)eventArray
{
NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
//get sorted stored records
NSArray *fetchedRecords = [self.fetchedResultsController fetchedObjects];
//sort dictionaries
NSSortDescriptor *aSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"id" ascending:YES];
NSArray *downloadedRecords = [self.events sortedArrayUsingDescriptors:[NSArray arrayWithObject:aSortDescriptor]];
NSLog(@"DOWNLOADED EVENTS = %@", downloadedRecords);
NSLog(@"FETCHED EVENTS = %@", fetchedRecords);
//if store is not empty we need to walk through data and add/update records, otherwise/ELSE we need to import initial data
if (fetchedRecords.count != 0) {
//stores has records already
NSLog(@"FIND OR CREATE PROCESS");
if ([downloadedRecords count] > 0) {
NSArray *storedRecords = [self fetchEvents:eventArray withContext:context];
NSUInteger currentIndex = 0;
for (NSDictionary* event in downloadedRecords) {
Event* eventObject = nil;
if ([storedRecords count] > currentIndex) {
eventObject = [storedRecords objectAtIndex:currentIndex];
}
NSLog(@"STRING VALUE OF KEY = %@", [[eventObject valueForKey:@"eventID"]stringValue]);
if ([[event valueForKey:@"id"] isEqualToString:[[eventObject valueForKey:@"eventID"] stringValue]]) {
//Update Record
NSLog(@"Updating Record!!!");
[self updateManagedObject:eventObject withRecord:event inContext:context];
}
else
{
//New Record
NSLog(@"Inserting Record!!!");
eventObject = (Event*)[NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:context];
eventObject.eventID = [self makeNumberFromString:[event valueForKey:@"id"]];
eventObject.title = [event valueForKey:@"title"];
eventObject.venue = [event valueForKey:@"venue"];
}
currentIndex++;
}
}
}
else
{
//import initial data
NSLog(@"IMPORTING INITIAL DATA");
for (NSDictionary* event in downloadedRecords) {
Event *eventObject = (Event*)[NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:context];
eventObject.eventID = [self makeNumberFromString:[event valueForKey:@"id"]];
eventObject.title = [event valueForKey:@"title"];
eventObject.venue = [event valueForKey:@"venue"];
}
}
// Save the context.
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
}
The FETCHEVENTS method:
-(NSArray*)fetchEvents:(NSArray*)eIDs withContext:(NSManagedObjectContext*)context
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(eventID IN %@)", eIDs];
[fetchRequest setPredicate:predicate];
[fetchRequest setSortDescriptors:@[ [[NSSortDescriptor alloc] initWithKey: @"eventID" ascending:YES] ]];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
NSLog(@"No rows returned");
}
return fetchedObjects;
}
The Update Object method:
- (void)updateManagedObject:(NSManagedObject*)object withRecord:(NSDictionary*)record inContext:(NSManagedObjectContext*)context
{
[object setValue:[self makeNumberFromString:[record valueForKey:@"id"]] forKey:@"eventID"];
[object setValue:[record valueForKey:@"title"] forKey:@"title"];
[object setValue:[record valueForKey:@"venue"] forKey:@"venue"];
}
I'm calling findOrCreate method once I download the web service data and parse it.
Let me know if you have any other questions.