Database update using Core Data - iphone

I am trying to update my local database when app gets response from the web server. When app gets the update from web server, I fetch the data from the local database by matching the id with the response and get one row and perform update code but local database does not get updated and also does not give an error.
What should be the solution???
-(void)checkID:(NSMutableDictionary *)dict
{
NSDictionary *dictEvent = [dict objectForKey:#"Event"];
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObject *selectedManagedObject = nil;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Events" inManagedObjectContext:context];
NSSortDescriptor *sortDescObj = [[NSSortDescriptor alloc] initWithKey:#"event_id" ascending:YES];
NSError *error = nil;
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"user_id=%# and event_id=%#",[NSNumber numberWithInt:[[dictEvent valueForKey:#"user_id"] intValue]],[NSNumber numberWithInt:[[dictEvent valueForKey:#"id"] intValue]]]];
NSLog(#"Predicate = %#",predicate);
NSArray *arrSortDescriptors = [NSArray arrayWithObject:sortDescObj];
[fetchRequest setSortDescriptors:arrSortDescriptors];
[fetchRequest setEntity:entity];
[fetchRequest setReturnsDistinctResults:YES];
[fetchRequest setPredicate:predicate];
NSArray *arrResult = [context executeFetchRequest:fetchRequest error:&error];
if ([arrResult count]>0)
{
NSArray *arrKey = [dictEvent allKeys];
NSArray *arrValue = [dictEvent allValues];
NSLog(#"ArrKey : %#\nArrValue : %#",arrKey,arrValue);
selectedManagedObject = [arrResult objectAtIndex:0];
for(int i = 0; i < [arrKey count] ; i++)
{
NSLog(#"selectedMng :- %#",selectedManagedObject);
NSLog(#"KEY: %#\t: %#",[arrKey objectAtIndex:i],[arrValue objectAtIndex:i]);
if ([[arrKey objectAtIndex:i]isEqualToString:#"id"])
{
[selectedManagedObject setValue:[arrValue objectAtIndex:i] forKey:#"event_id"];
}
else if([[arrKey objectAtIndex:i]isEqualToString:#"invited_status"])
{
[selectedManagedObject setValue:[arrValue objectAtIndex:i] forKey:#"invite_status"];
}
else
{
[selectedManagedObject setValue:[arrValue objectAtIndex:i] forKey:[arrKey objectAtIndex:i]];
}
}
if (! [selectedManagedObject.managedObjectContext save:&error])
{
NSLog(#"updateEntityIntoDataBaseNamed - Error :: %#", [error localizedDescription]);
}
// }
}
}

Besides modifying your predicate as suggested by #Martin
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"user_id=%# && event_id=%#",
[NSNumber numberWithInt:[[dictEvent valueForKey:#"user_id"] intValue]],
[NSNumber numberWithInt:[[dictEvent valueForKey:#"id"] intValue]]
];
note that in two cases, you are updating your object using non matching keys: this happens for id and event_id, and for invited_status and invite_status.

You cannot use stringWithFormat within predicateWithFormat. Your predicate should probably look like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"user_id=%# and event_id=%#",
[NSNumber numberWithInt:[[dictEvent valueForKey:#"user_id"] intValue]],
[NSNumber numberWithInt:[[dictEvent valueForKey:#"id"] intValue]]
];

Related

Function in NSManagedObjectClass is failing

I have a NSManagedObjectClass Favorites. In this class I have a method getFavoritesByArtistId You can see it over here.
-(Favorites *)getFavoriteById:(int)art_id{
Favorites *favorite;
NSLog(#"artist is is %d",art_id);
RKManagedObjectStore *store = [[GenkonStageDataModel sharedDataModel] objectStore];
NSManagedObjectContext *context = store.mainQueueManagedObjectContext;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Favorites"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:
#"fav_art_id == %d",art_id];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:#"fav_id" ascending:YES];
fetchRequest.sortDescriptors = #[descriptor];
NSArray *matches = [context executeFetchRequest:fetchRequest error:nil];
if (matches.count > 0){
NSLog(#"till here");
favorite = [matches objectAtIndex:0];
}else {
NSLog(#"till here 2");
return NULL;
}
return favorite;
}
In my view controller I am calling it like this.
RKManagedObjectStore *store = [[GenkonStageDataModel sharedDataModel] objectStore];
NSManagedObjectContext *context = store.mainQueueManagedObjectContext;
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Favorites" inManagedObjectContext:context];
Favorites* favClass = [[Favorites alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:context];
Favorites *favorite = [favClass getFavoriteById:[artist.art_id intValue]];
Next I'm going to check
if(![favorite isKindOfClass:[NSNull class]]){
//Artist is already favorized !
}else{
//Artist is not favorized !
}
But my app always crashes with this CoreData _PFFastEntityRangesByType + 12, stop reason = EXC_BAD_ACCESS (code=1, address=0x38)
Any help?

CoreData compare two NSManagedObjects by their attributes and relationships

I have filter object. It has several attributes and relationships. I want to create new filter object if there's no one with the same attributes & relationships. How to accomplish this ?
I would choose a more general approach..
I would take the NSEntityDescriptions of the object and build a predicate with all properties in that Description.
so like..
- (void)insertIfUnique:(NSManagedObject*)obj inContext:(NSManagedObjectContext*)ctx {
NSMutableString *format = [NSMutableString string];
NSEntityDescription *desc = obj.entity;
NSArray *attrs = desc.attributeKeys;
for(NSString *attr in attrs) {
if(format.length)
[format appendString:#" AND "];
[format appendFormat:#"%#==%#", attr, [obj valueForKey:attr]];
}
NSPredicate *p = [NSPredicate predicateWithFormat:format];
NSFetchRequest *f = [[NSFetchRequest alloc] initWithEntityName:desc.name];
f.predicate = p;
if([ctx countForFetchRequest:f error:nil]==0)
[ctx insertObject:obj];
}
You have to manually search CoreData for any existing filter objects. If not found, you can process to create a new filter:
Here is one helper function
+(id)uniqueEntityfForName:(NSString *)name
withValue:(id)value
forKey:(NSString *)key
inManagedObjectContext:(NSManagedObjectContext *)context {
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
request.entity = [NSEntityDescription entityForName:name inManagedObjectContext:context];
request.predicate = [NSPredicate predicateWithFormat:[key stringByAppendingString:#" == %#"], value];
NSArray *result = [context executeFetchRequest:request error:nil];
id entity = [result lastObject];
if (entity == nil) {
entity = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:context];
[entity setValue:value forKey:key];
} else {
entity = [result lastObject];
}
return entity;
}
I use this method like this:
SomeEntity *entity = [CDUtils uniqueEntityfForName:#"SomeEntity" withValue:#"foo" forKey:#"bar" inManagedObjectContext:context];
You may have to define your own predicate.

NSSortDescriptor not being called

I'm trying to execute a fetch request on an entity Folders, and I want a folder named xyz to be the last object when sorted.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Folder" inManagedObjectContext:appDelegate.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *lastDescriptor =
[[[NSSortDescriptor alloc] initWithKey:#"folderName" ascending:YES comparator:^NSComparisonResult(NSString* name1, NSString* name2) {
NSLog(#"descriptor");
if ([name1 isEqualToString:#"xyz"]) {
return NSOrderedAscending;
}
if ([name2 isEqualToString:#"xyz"]) {
return NSOrderedDescending;
}
return [name1 compare:name2];
}] autorelease];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:lastDescriptor]];
[fetchRequest setFetchBatchSize:5];
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:appDelegate.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
self.fetchedResultsController.delegate=self;
[fetchRequest release];
[theFetchedResultsController release];
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
exit(-1); // Fail
}
But none of the NSLog statements are being called. Are they supposed to? And the folder xyz does not appear last, but everything ends up being sorted in alphabetical order. Am I doing something wrong?
Edit: Posted full code
This code (your code) works:
- (void)sortMe {
NSDictionary *d0 = [NSDictionary dictionaryWithObject:#"efg" forKey:#"folderName"];
NSDictionary *d1 = [NSDictionary dictionaryWithObject:#"xyz" forKey:#"folderName"];
NSDictionary *d2 = [NSDictionary dictionaryWithObject:#"abc" forKey:#"folderName"];
NSDictionary *d3 = [NSDictionary dictionaryWithObject:#"def" forKey:#"folderName"];
NSArray *testMe = [NSArray arrayWithObjects:d0, d1, d2, d3, nil];
NSSortDescriptor *lastDescriptor =
[[NSSortDescriptor alloc] initWithKey:#"folderName" ascending:YES comparator:^NSComparisonResult(NSString* name1, NSString* name2) {
NSLog(#"descriptor");
if ([name1 isEqualToString:#"xyz"]) {
return NSOrderedAscending;
}
if ([name2 isEqualToString:#"xyz"]) {
return NSOrderedDescending;
}
return [name1 compare:name2];
}];
NSArray *sorted = [testMe sortedArrayUsingDescriptors:[NSArray arrayWithObject:lastDescriptor]];
for (NSDictionary *d in sorted) {
NSLog(#"value=%#", [d valueForKey:#"folderName"]);
}
}
I predict this code will work, too:
NSError *error;
NSArray *result = [appDelegate.managedObjectContext executeFetchRequest:fetchRequest error:&error];
// log the array
I think the problem is in the NSFetchedResultsController delegate setup, elsewhere in the code.

Core Data iPhone - Loading a String

I am having troubles with understanding how to load data with Core Data. This is what I have:
Entity named 'People'
Attributes of this entity named 'firstName' (string), 'lastName' (string), 'isSpecial' (boolean), 'isVerySpecial' (boolean).
I want to get the first and last name of any person who is special or very special so that I can then put those names into labels and wherever I like as I wish. I have played about with fetch requests without luck.
Any help would be much appreciated, thanks.
Something like this should do it:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *weightEntity = [NSEntityDescription entityForName:#"Person" inManagedObjectContext:[[yourCoreDataManager sharedInstance] managedObjectContext]];
[fetchRequest setEntity:weightEntity];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"isSpecial == %# OR isVerySpecial == %#", [NSNumber numberWithBool:YES], [NSNumber numberWithBool:YES]]];
NSError *error = nil;
NSArray *result = [[yourCoreDataManager sharedInstance] managedObjectContext] executeFetchRequest:fetchRequest error:&error];
And then:
Person *person = [result objectAtIndex:0];
NSString *lastName = person.lastName;
NSString *firstName = person.firstName;
Something like that should do the trick:
self.fetchedResultsController = [Person fetchAllSortedBy:#"lastName" ascending:YES withPredicate:[NSPredicate predicateWithFormat:#"isSpecial == %# OR isVerySpecial == %#", [NSNumber numberWithBool:YES], [NSNumber numberWithBool:YES]] groupBy:nil delegate:self];
then you will get an array of persons in your fetchedResultsController. To get it simple use
NSMutableArray *yourArray = [NSMutableArray arrayWithArray: self.fetchedResultsController.fetchedObjects];
Hope it helps

NSPredicate - Not working as expected

I have the following code in place:
NSString *mapIDx = #"98";
NSLog(#"map id: %#", mapIDx);
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"WayPoint" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
//NSPredicate *predicate = [NSPredicate predicateWithFormat:#"waypoint_map_id=%#", mapIDx];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"waypoint_map_id==%#", mapIDx];
[request setPredicate:predicate];
NSError *error;
listArray = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
[request release];
int arrayItemQuantity = [listArray count];
NSLog(#"Array Quantity: %d", arrayItemQuantity);
// Loop through the array and display the contents.
int i;
for (i = 0; i < arrayItemQuantity; i++)
{
NSLog (#"Element %i = %#", i, [listArray objectAtIndex: i]);
}
/*
NSInteger *xCoordinate = listArray[1];
NSInteger *yCoordinate = listArray[3];
NSLog(#"xCoordinate: %#", xCoordinate);
NSLog(#"yCoordinate: %#", yCoordinate);
CLLocationCoordinate2D coordinate = {xCoordinate, yCoordinate};
MapPin *pin = [[MapPin alloc]initwithCoordinates:coordinate];
[self.mapView addAnnotation:pin];
[pin release];
*/
[listArray release];
As you can see I'm trying to select specific objects from my database, anything with a waypoint_map_id of 98, but the NSPredicate is not working as I expected. Zero objects are getting selected.
Anyone any thoughts ?
The predicate with format does not covert the string "98" to a number. Instead it does
waypoint_map_id == "98"
... which is looking for string attribute. Change the predicate to:
NSInteger mapIdx=98;
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"waypoint_map_id==%d", mapIDx];
... which returns a predicate of:
waypoint_map_id == 98
Assuming that you definately have that object in your database, try adding quotes around the value?
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"waypoint_map_id==\"%#\"", mapIDx];
(clutching at straws!)
Your prediacte looks fine so I would instantly start to suspect the bug is somewhere else :
Is there definintely a waypoint with that id?
Is listArray nil i.e. something else has gone wrong with the request?
You don't check to see what the error is - perhaps that will give you more information?
NSError *error = nil;
NSArray *results = [managedObjectContext executeFetchRequest:request error:&error];
[request release];
if (nil == results || nil != error)
NSLog(#"Error getting results : %#", error);
listArray = [results mutableCopy];
Hope that's helpful at all!
Problem solved:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"waypoint_map_id contains[cd] %#", mapIDx];
[request setPredicate:predicate];