NSPredicate problem with fetchedResultsController - core-data

Please help! I've been trying to figure this out for way too long.
I can't seem to use an NSPredicate in my fetchedResultsController method:
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil) return fetchedResultsController;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Tweet" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"column == 0"];
[fetchRequest setPredicate:predicate];
[fetchRequest setReturnsObjectsAsFaults:NO];
[fetchRequest setFetchBatchSize:20];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"created_at" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
return fetchedResultsController; }
Yet, in another method, where I simply check to see if an object exists, the predicate works like a charm:
- (BOOL)findObjectWithKey:(NSString *)key andValue:(NSString *)value sortBy:(NSString *)sort {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Tweet" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"%K == %#", key, value];
[request setPredicate:predicate];
[request setReturnsObjectsAsFaults:NO];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sort ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
aFetchedResultsController.delegate = self;
NSError *error = nil;
NSArray *result = [managedObjectContext executeFetchRequest:request error:&error];
[aFetchedResultsController release];
[request release];
[sortDescriptor release];
[sortDescriptors release];
if ((result != nil) && ([result count]) && (error == nil)) {
return TRUE;
} else {
return FALSE;
}}
What am I doing wrong? Thanks in advance!

Assuming your "column" attribute is a number, you should compare it to an NSNumber object like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"column == %#",[NSNumber numberWithInteger:0]];

Since column is a property on the entity then your predicate logic is fine. What results are you seeing that indicate the predicate is not working?

Related

coredata subquery with multiple conditions / relations

I have the following model:
how can I get all the PT objects where groupId == '2'?
I have tried several ways, but without success.
With this query, I get one result only:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"Status" inManagedObjectContext:self.managedObjectContext];
request.predicate = [NSPredicate predicateWithFormat:#"group.groupId == %#", [NSNumber numberWithInt:2]];
NSError *error = nil;
NSArray *resultSet = [self.managedObjectContext executeFetchRequest:request error:&error];
[request release];
NSLog(#"array count: %lu", (unsigned long)[resultSet count]);
NSPredicate *thePredicate = [NSPredicate predicateWithFormat:#"hasBeenDeleted == %# AND (ANY hasStatus IN %#)",
[NSNumber numberWithBool:NO],
[NSSet setWithArray:resultSet]];
[self.ptListViewController refreshDataWithPredicate:thePredicate];
You could start with a template "GROUP_BY_GROUP_ID" and add it to the managedObjectModel ...
- (NSManagedObjectModel *)managedObjectModel {
// The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"GroupdId2" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSFetchRequest *tmpTemplate;
NSEntityDescription *tmpEntity;
NSPredicate *tmpPredicate;
// 1. GROUP_BY_GROUP_ID
tmpEntity = [[_managedObjectModel entitiesByName] objectForKey:#"Group"];
tmpTemplate = [[NSFetchRequest alloc] init];
[tmpTemplate setEntity:tmpEntity];
tmpPredicate = [NSPredicate predicateWithFormat:#"(groupId == $value)"];
[tmpTemplate setPredicate:tmpPredicate];
[_managedObjectModel setFetchRequestTemplate:tmpTemplate forName:#"GROUP_BY_GROUP_ID"];
return _managedObjectModel;
}
Here is the appropriate fetch method:
- (NSArray *)fetchGroupByGroupId:(NSNumber *)value
{
NSError *error = nil;
NSManagedObjectModel *model = _managedObjectModel;
NSDictionary *substitutionDictionary = [NSDictionary dictionaryWithObjectsAndKeys:value, #"value", nil];
NSFetchRequest *fetchRequest = [model fetchRequestFromTemplateWithName:#"GROUP_BY_GROUP_ID" substitutionVariables:substitutionDictionary];
NSArray *results = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
return results;
}
Now you can start fetching PT entities like this (Xcode lets you generate the NSManagedObject subclasses for all entities):
NSArray *groups=[self fetchGroupByGroupId:#(2)];
NSMutableSet *resultPT=[[NSMutableSet alloc] init];
for (Group *group in groups) {
for (Status *status in group.hasStatus) {
for (PTStatus *ptstatus in status.ptStatus) {
if (ptstatus.targetPT!=nil) {
[resultPT addObject:ptstatus.targetPT];
}
if (ptstatus.pt!=nil) {
[resultPT addObject:ptstatus.pt];
}
}
}
}
In resultPT now you will find all different PT entities "with" groupId == '2'.
You find a XCode 6.1 project here: XCode 6.1 project on Dropbox.
Hope it helps.
I found it!
I had a bug when relating the Status with the Group.
Correct code for achieving:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"PTStatus" inManagedObjectContext:self.managedObjectContext];
request.predicate = [NSPredicate predicateWithFormat:#"ANY status.group.groupId == %#", [NSNumber numberWithInt:2]];
NSError *error = nil;
NSArray *resultSet = [self.managedObjectContext executeFetchRequest:request error:&error];
[request release];
NSLog(#"array count: %lu", (unsigned long)[resultSet count]);
NSPredicate *thePredicate = [NSPredicate predicateWithFormat:#"hasBeenDeleted == %# AND (ANY hasStatus IN %#)",
[NSNumber numberWithBool:NO],
[NSSet setWithArray:resultSet]];
[self.ptListViewController refreshDataWithPredicate:thePredicate];
and [self.ptListViewController refreshDataWithPredicate:thePredicate]; has
- (void)refreshDataWithPredicate:(NSPredicate *)predicate{
self.fetchedResultsController = nil;
[NSFetchedResultsController deleteCacheWithName:#"PTs_Cache"];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"PT" inManagedObjectContext:self.managedObjectContext];
request.sortDescriptors = [NSArray arrayWithObjects:
[NSSortDescriptor sortDescriptorWithKey:#"requestDate" ascending:NO],
[NSSortDescriptor sortDescriptorWithKey:#"number" ascending:YES],
nil];
request.predicate = predicate;
request.fetchBatchSize = 40;
NSString *sectionNameKeyPathString = #"dateSection_transient";
NSFetchedResultsController *frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:sectionNameKeyPathString
cacheName:#"PTs_Cache"];
[request release];
self.fetchedResultsController = frc;
[frc release];
[self.theTable reloadData];
}

iOS Core Data error when updating

I want to update a field in a table. However when I save after fetching and modifying the field, error 1570 is thrown. [Mandatory value is nil].
MyAppDelegate *appdelegate = DELEGATE;
NSManagedObjectContext *context = [appdelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"MyTable" inManagedObjectContext:context];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(myAttribute_id = %#)",myAttribute.attribute_id];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
for (myAttribute *obj in results) {
NSLog(#"myAttribute_id : %#",myAttribute.attribute_id);
[obj setValue:myAttribute.attribute2_id forKey:#"attribute2_id"];
[context save:&error];
NSLog(#"save error : %#",error);
}
Here I get an error. Whereas all mandatory fields are already set.

NSPredicate with 20 last records

I'm working with core data and I try to get last 20 records using setFecthLimit but in these last records I want to get count of unreads, I use this
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Post" inManagedObjectContext:_managedObjectContext];
[request setEntity:entity];
[request setFetchLimit:20];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"isRead = NO OR isRead = NIL"];
[request setPredicate:predicate];
NSError *error = nil;
NSMutableArray *records = [[_managedObjectContext
executeFetchRequest:request
error:&error] mutableCopy];
but it always return me 20, can anyone help me please?
A simple solution is to remove the predicate. Grab 20 objects and then filter them based on the predicate.
For example:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Post" inManagedObjectContext:_managedObjectContext];
[request setEntity:entity];
[request setFetchLimit:20];
NSError *error = nil;
NSArray *records = [_managedObjectContext executeFetchRequest:request
error:&error];
// do some error checking here...
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"isRead = NO OR isRead = nil"];
// [NSPredicate predicateWithFormat:#"isRead = %#", [NSNumber numberWithBool:NO]];
NSArray *filteredRecords = [records filteredArrayUsingPredicate:predicate];
I think you have a typo in your predicate format:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Post"]
request.fetchLimit = 20;
request.predicate = [NSPredicate predicateWithFormat:#"(isRead == NO) OR (isRead == NULL)"];
NSSortDescriptor = [...insert your sort descriptor code here...]
request.sortDEscriptos = #[sd];
And remember to sort, such that you get the last 20, not just a random 20.

Core Data Sort Descriptors with relationships between Entities

I have two entities, Job and Client. The relationship from job to client is called clientOfJob which is a many-to-one relationship:
Job<<-->Client
I am trying to understand how I would sort my fetch results into sections for the table view, with the sections based on client first names.
This is my first attempt to use sectionNameForKeyPath, but I am using sample code from CoreDataBooks, and so far, substituting some of that code has eliminated some serious problems I had earlier today.
Here is the code I tried. I didn't think it would work, but I'm not sure what I need to use for the client sort descriptor key and for the sectionNameKeyPath.
By the way, the code works well with only the jobSortDescriptor (without the clientSortDescriptor) and with sectionNameKeyPath set to nil. Then it just sorts by job description. I can get at the related client entity information, putting client name information into the detailedTextLabel of each cell while I have the job description in the textLabel of the cell.
- (NSFetchedResultsController *) fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription * entity = [NSEntityDescription entityForName:#"Job" inManagedObjectContext:dataInterface.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:10];
NSSortDescriptor *clientSortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"clientOfJob.firstName" ascending:YES];
NSSortDescriptor *jobSortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"jobDescription" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:clientSortDescriptor, jobSortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:dataInterface.managedObjectContext sectionNameKeyPath:#"clientOfJob.firstName" cacheName:#"Jobs"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[jobSortDescriptor release];
[clientSortDescriptor release];
[sortDescriptors release];
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(#"Unresolved Error %#, %#", error, [error userInfo]);
abort();
}
return fetchedResultsController;
}

CoreData: fetch only last elements, not all (iPhone)

Welcome
i use Core Data to store datas. i need such a method which returns only the last 7 elements of entity. my question is how should i modify this code ( it fetchs all of elements, but i need only last 7)
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Trip" inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[ NSFetchRequest alloc] init];
[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"distance" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
NSError *error;
tripArray = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
Define last? Core Data does not have a concept of order internally. If you mean by the farthest away based on your distance property then you can do the following:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Trip" inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[ NSFetchRequest alloc] init];
[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"distance" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[request setSortDescriptors:sortDescriptors];
[request setFetchLimit:7];
[sortDescriptor release];
NSError *error;
NSArray *tripArray = [managedObjectContext executeFetchRequest:request error:&error];
Note that the addition of the -setFetchLimit: will cause this request to only return 7 results. It will return the "first" 7 based on your sort. So if you want the closest, reverse the ascending: portion of your sort.
-mutableCopy
There is absolutely no point in calling -mutableCopy on the NSArray that is returned from -executeFetchRequest: error:. Adding objects to that NSArray will not add them to Core Data and removing them from that NSArray will not remove them from Core Data. Therefore it has absolutely no value and is just wasteful.
Do you remember where you saw that? I have been trying to track it down for a while now.

Resources