Problem with Core Data - EXC_BAD_ACCESS - objective-c

I'm using the following code and I'm getting an EXC_BAD_ACCESS when trying to get the count of objects - anyone have any idea why? Oddly enough, the error only happens if the count should be one or greater, if there are no objects it seems to work fine (it outputs null).
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"TVShow" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
[fetchRequest includesPendingChanges];
//NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ID == %#", showId];
//[fetchRequest setPredicate:predicate];
NSError *error;
NSLog(#"Generating Count");
NSUInteger count = [[self managedObjectContext] countForFetchRequest:fetchRequest error:&error];
if(count == NSNotFound) {
NSLog(#"error");
}
else {
NSLog(#"%#", count); // EXC_BAD_ACCESS here
}
[fetchRequest release];

Use %d instead of %# in format strings for integers:
NSLog(#"%d", count);
Here's a list of String Format Specifiers.

Related

Saving data in background thread doesn't work

I am trying to save my data in CoreData in background thread, but it crash or it doesnt work, any idea where am I doing the mistake?
When I try with main thread it works correctly, I tried to google to find some information in background thread, I couldn't find some useful article about it.
any help appreciate.
Thanks
This is the objective -c code, what I tried
-(void)insertNameAndSurnameInDataBase:(NSString *)name surname:(NSString *)surname numbers:(NSArray *)numbers labels:(NSArray *)labels{
NSManagedObjectContext *backgroundMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[backgroundMOC performBlock:^{
NSError *error;
NameAndSurname *nameAndSurname = [NSEntityDescription insertNewObjectForEntityForName:#"NameAndSurname" inManagedObjectContext:backgroundMOC];
NSString *nSurname = [NSString stringWithFormat:#"%# %#",name,surname];
nameAndSurname.nameSurname = nSurname;
if ([backgroundMOC save:&error]) {
}
else{
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"NameAndSurname"
inManagedObjectContext:backgroundMOC];
// predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"nameSurname =[c] %#", nSurname];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];
[fetchRequest setReturnsObjectsAsFaults:NO];
NSArray *fetchedObjects = [backgroundMOC executeFetchRequest:fetchRequest error:&error];
if([fetchedObjects count] > 0){
[numbers enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
id obj2 = [labels objectAtIndex:idx];
obj = [obj stringByReplacingOccurrencesOfString:#" " withString:#""];
ContactNumber *phoneNumber = [NSEntityDescription insertNewObjectForEntityForName:#"ContactNumber" inManagedObjectContext:backgroundMOC];
phoneNumber.number = obj;
phoneNumber.label = obj2;
phoneNumber.nameAndSurname = fetchedObjects[0];
NSError *error;
if ([backgroundMOC save:&error]) {
}
else{
}
}];
}
}];
}

NSFetchedResultsController for new object

I have UITableViewController with static editable cells. In my UITableViewController I make CoreData object, like this:
- (User*)user {
if (_user == nil) {
_user = [NSEntityDescription insertNewObjectForEntityForName:TABLE_USER inManagedObjectContext:self.managedObjectContext];
NSError* error;
[self.managedObjectContext save:&error];
if (error != nil) {
abort();
}
}
return _user;
}
I want to get the object in NSFetchedResultsController that would display its fields in a table, and then save the object.
I'm trying to do:
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:TABLE_USER_PROFILE inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"lastName" ascending:NO];
NSArray *sortDescriptors = #[sortDescriptor];
NSPredicate* pred = [NSPredicate predicateWithFormat:#"%# = %#", TABLE_USER, self.user];
[fetchRequest setPredicate:pred];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:TABLE_USER];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
abort();
}
return _fetchedResultsController;
}
But it didn't work. I get empty fetchedResultsController.
If self.user is a NSManagedObject and you query against a User entity you could try to edit your predicate like the following:
NSPredicate* pred = [NSPredicate predicateWithFormat:#"self == %#", self.user];
Hope that helps.
P.S. If my answer doesn't work try to provide some other details (see my comment)

Fetching a maximum value with CoreData

This is the first time I'm trying to use CoreData and I'm having some trouble getting the max date from a a table.
This is basically what I'm trying to do:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Radar" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:#"modifiedOn"];
NSExpression *maxDate = [NSExpression expressionForFunction:#"max:" arguments:[NSArray arrayWithObject:keyPathExpression]];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:#"maxDate"];
[expressionDescription setExpression:maxDate];
[expressionDescription setExpressionResultType:NSDateAttributeType];
[request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];
NSError *error = nil;
NSArray *objects = [managedObjectContext executeFetchRequest:request error:&error];
if (objects == nil) {
// Handle the error.
}
else {
if ([objects count] > 0) {
NSLog(#"%d", [objects count]);
NSLog(#"MAx date: %#", [[objects objectAtIndex:0] valueForKey:#"modifiedOn"]);
}
}
This code somehow does the opposite of what I want and print the minimum date. Since I've just started with CoreData it's obvious that I got something wrong, but what?
Maybe you should try to NSLog the [objects lastObject],instead of first one?

How to Update and Delete the required recored of a table usning Core Data

I am learning the core data
How to delete and update the data using core data. I have worked on upload and fetch. I need to write the methods for delete and update. Please tell me how to update and delete a recode using core data.
Below I have written code for upload and fetch data from table using core data.
-(void)uploadData
{
Employee *empObj=(Employee *)[NSEntityDescription insertNewObjectForEntityForName:#"Employee" inManagedObjectContext:self.managedObjectContext];
empObj.empId=[NSNumber numberWithInt:12345];
empObj.empSalary=[NSNumber numberWithInt:25000];
empObj.empName=#"Venu";
empObj.empDesignation=#"Programmer";
empObj.empExp=#"2 Years";
if ([self.managedObjectContext hasChanges] )
{
[self.managedObjectContext save:nil];
}
}
-(void)fetchData
{
NSEntityDescription *empEntity = [NSEntityDescription entityForName:#"Employee" inManagedObjectContext:self.managedObjectContext];
// Setup the fetch request
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
NSArray *fatherArray=[self.managedObjectContext executeFetchRequest:request error:nil];
[request setEntity:empEntity];
NSArray *empArray=[self.managedObjectContext executeFetchRequest:request error:nil];
for (int i=0; i<[empArray count]; i++)
{
printf("\n=================================Recored== %d==================================== ",i);
Employee *empObj=[empArray objectAtIndex:i];
printf("\n obj.empName========= %s",[empObj.empName UTF8String]);
printf("\n obj.empDesignation========= %s",[empObj.empDesignation UTF8String]);
printf("\n obj.empExp========= %s",[empObj.empExp UTF8String]);
printf("\n obj.empId========= %d",[empObj.empId intValue]);
printf("\n obj.empSalary========= %d",[empObj.empSalary intValue]);
printf("\n============================================================================= ");
}
}
I am doing a project which involved in Core Data, and I would
like to share something with you about it.
It is a clear that before you delete or update a record you need
to retrieve that record.
Use the employee with empId 12345 as an example,
a)Delete
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#:#"Employee"
inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSPredicate *pred = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"empId = %d", 12345]];
[request setPredicate:pred];
NSArray *empArray=[self.managedObjectContext executeFetchRequest:request error:nil];
[request release];
if ([empArray count] > 0){
Employee *employee = [empArray objectAtIndex:0];
[self.managedObjectContext deleteObject:employee];
[self.managedObjectContext save:nil];
}
b) update
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#:#"Employee"
inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSPredicate *pred = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"empId = %d", 12345]];
[request setPredicate:pred];
NSArray *empArray=[self.managedObjectContext executeFetchRequest:request error:nil];
[request release];
if ([empArray count] > 0){
Employee *employee = [empArray objectAtIndex:0];
employee.empSalary=[NSNumber numberWithInt:45000];
employee.empName=#"John";
employee.empDesignation=#"Analysist";
employee.empExp=#"4 Years";
[self.managedObjectContext save:nil];
}
After a successful fetch-request, you can delete your objects simply by asking the managed objectcontext to delete them:
for (NSManagedObject *managedObject in items) {
[self.managedObjectContext deleteObject:managedObject];
DebugLog(#"%# object deleted",entityDescription);
}
if (![self.managedObjectContext save:&error]) {
DebugLog(#"Error deleting %# - error:%#",entityDescription,error);
}
Updating is done in a similar way, fetch the object desired, change the value, and save the context.

How do you create a Set of Entities which all have Relations to other Entities with Specific Attributes? In Core Data

I've got a Core Data entity called "Card" which has a relationship "info" to another entity, "CardInfo". It's a one-to-many relationship: each card can have multiple CardInfos, but each CardInfo only has one Card.
The CardInfo entity just has two strings, "cardKey" and "cardValue". The object is to allow for arbitrary input of data for cards. Say, you wanted to know what color a card was. Then you added a CardInfo to each Card that had a cardKey of "color" and a cardValue of "black" or "red".
My general question is: what's the best way to get the set of Cards where each Card has a CardInfo where the CardKey and CardValue has specific values. For example: all Cards with relationship to CardInfo cardKey='color' and cardValue='red'? Ideally, I return an NSSet of all the appropriate Card * objects.
The loop at the end is not needed. A simple KVC call will clean it up nicely.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:#"CardInfo" inManagedObjectContext:self.managedObjectContext]];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"cardKey = %# AND cardValue = %#", thisKey, thisValue]];
NSError *error = nil;
NSArray *items = [[self managedObjectContext executeFetchRequest:fetchRequest error:&error];
[fetchRequest release], fetchRequest = nil;
NSAssert1(error == nil, #"Error fetching objects: %#\n%#", [error localizedDescription], [error userInfo]);
return [items valueForKeyPath:#"#distinctUnionOfObjects.card"];
This is the answer that I came up with, but the two-part process seems inefficient to me. I figure there must be a more elegant way to do this with key-values or something
-(NSSet *)cardsWithCardKey:(NSString *)thisKey cardValue:(NSString *)thisValue {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"CardInfo"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate
predicateWithFormat:#"(cardKey=%#) AND (cardValue=%#)",
thisKey,thisValue];
[fetchRequest setPredicate:predicate];
NSError *error;
NSArray *items = [self.managedObjectContext
executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
NSMutableSet *cardSet = [NSMutableSet setWithCapacity:[items count]];
for (int i = 0 ; i < [items count] ; i++) {
if ([[items objectAtIndex:i] card] != nil) {
[cardSet addObject:[[items objectAtIndex:i] card]];
}
}
return [NSSet setWithSet:cardSet];
}