NSFetchedResultsController with complicate predicate - ios

I'm developing the app with UICollectionView.
It's collection of events arranged by date. I'm using NSFetchedResultsController to fetch data from DB. But I need to fetch current and future events + 2 past events.
For NSFetchRequest I'm using NSCompoundPredicate
NSPredicate *nextPredicate = [NSPredicate predicateWithFormat: #"startAt >= %#", [NSDate date]];
NSPredicate *previousPredicate = [NSPredicate predicateWithFormat:#"startAt < %#", [NSDate date]];
NSCompoundPredicate *resultPredicate = [NSCompoundPredicate andPredicateWithSubpredicates: #[nextPredicate, previuosPredicate]];
fetchRequest.predicate = resultPredicate;
And I have no idea how to limit previousPredicate to receive only 2 items.

If you know the date of current event than create a method that return date of the last event to fetch and then set the predicate on the main NSFetchRequest to that date.
-(NSDate *)dateOfPastEvent{
NSFetchRequest *request = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"EntityName" inManagedObjectContext:_mainContext];
[request setEntity:entity];
NSSortDescriptor *sortDesc = [NSSortDescriptor sortDescriptorWithKey:#"startAt" ascending:NO];
[request setSortDescriptors:#[sortDesc]];
NSError *error = nil;
NSArray *array = [_mainContext executeFetchRequest:request error:&error];
__block NSDate *pastEventDate;
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
if ([obj valueForKey:#"startAt"] == currentEventDate) {
if (array.count >= idx+2) {
pastEventDate = [[array objectAtIndex:idx+2] valueForKey:#"startAt"];
*stop = YES;
}
}
}];
return pastEventDate;
}
Now set the predicate for the above returned date
NSFetchRequest *requestForController = [[NSFetchRequest alloc]init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"EntityName" inManagedObjectContext:_mainContext];
[requestForController setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"startAt >= %#", [self dateOfPastEvent]];

Related

Save the result of setPredicate to NSString

I have created NSPredicate to search the string in my coredata.
so in this case does anyone know how to save the result [fetchRequest setPredicate:predicate]; in NSString.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name CONTAINS[cd] %#",
mytext];
[fetchRequest setPredicate:predicate];
Write Your Table Name in #"YOUR_ENTITY_NAME"
Make sure that your table contains name column
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"YOUR_ENTITY_NAME"];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"name CONTAINS[cd] %#", mytext]];
NSMutableArray *arrResult = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
NSLog(#"%#", arrResult); //output
I think this will help you
NSArray *fetchedObjects;
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"your entity" inManagedObjectContext: context];
[fetch setEntity:entityDescription];
[fetch setPredicate:[NSPredicate predicateWithFormat:#"name CONTAINS[cd] %#", mytext]];
NSError * error = nil;
fetchedObjects = [context executeFetchRequest:fetch error:&error];
if([fetchedObjects count] == 1)
NSLog(#"%#",[fetchedObjects objectAtIndex:0]);

NSFetchRequest using NSPredicate

I am trying to create a NSArray of all results of a filtered search through a core data database in this way:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"AllFiles" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *p1 = [NSPredicate predicateWithFormat:#"userID == %#", userID];
NSPredicate *p2 = [NSPredicate predicateWithFormat:#"folderNumber == %d", folderNumber];
NSPredicate *p3 = [NSPredicate predicateWithFormat:#"fileType == %#", type];
NSPredicate *fetchPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:#[p1, p2, p3]];
[fetchRequest setPredicate:fetchPredicate];
NSError *error;
NSArray* returnArray = [context executeFetchRequest:fetchRequest error:&error];
The files are created in this way:
AllFiles *newFile = [NSEntityDescription
insertNewObjectForEntityForName:#"AllFiles"
inManagedObjectContext:context];
newFile.userID = userID;
newFile.folderNumber = [NSString stringWithFormat:#"%d", folderNumber];
....
As you can see I am trying to filter the results given some of the parameters:
#"userID == %#", userID
However all results are returned, without filtering... Any ideas why?
You are using an OR predicate, at least one of those 3 is matching for all. I suspect [NSPredicate predicateWithFormat:#"fileType == %#", type] is gathering all your files
Try compositing an AND like so...
NSPredicate *idPredicate = [NSPredicate predicateWithFormat:#"userID == %#", userID];
NSPredicate *folderNumPredicate = [NSPredicate predicateWithFormat:#"folderNumber == %d", folderNumber];
NSPredicate *typePredicate = [NSPredicate predicateWithFormat:#"fileType == %#", type];
NSPredicate *fetchPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:#[idPredicate, folderNumPredicate, typePredicate];
[fetchRequest setPredicate:fetchPredicate];
Bear in mind that andPredicateWithSubpredicates and orPredicateWithSubpredicates return a NSPredicate so they can be composited together in complex ways if you need.

core data :fetching data from entity

i have to use following query for fetching data:
SELECT * FROM t1.guides AS t1 JOIN guide_category_int AS t2 ON t1.id = t2.guide_id WHERE t2.category_id = 'category_id' AND t1.start_date >= 'today()' AND t1.end_date <= 'today()' ORDER BY t1.name ASC
How can I use this in core data?
Your fetch request will be something like this:
NSManagedObjectContext *context = ...
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Guides" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"guide.category_id == %# and start_date >= %# and end_date <= %#", #"category_id", [NSDate date], [NSDate date]]];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[sort release];
NSError *error;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if ([fetchedObjects count] > 0) {
//...
}
[fetchRequest release];
Also you can enable SQLDebug to see raw sql requests, and play with predicate and sort descriptor as you want. How to enable described there

NSPredicate returning all objects

I'm trying to use the NSPredicate to only get specific objects. The problem is that all the objects are fetched and it should only be specific objects where the condition is correct.
- (void)fetchDevices {
// Fetch the devices from persistent data store
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Songs"];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Songs" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
// retrive the objects with a given value for a certain property
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"selectedRow == %#" , selectedRowNumber];
devices = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[fetchRequest setPredicate:predicate];
}
The selectedRowNumber is an int declared in the .h file.
A look on my Songs entity:
PS. Please comment below if more information is required and i'll provide it.
You have to assign the predicate before executing the fetch request.
Also, if selectedRowNumber is an int then you have to use the %d format
instead of %#.
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"selectedRow == %d" , selectedRowNumber];
[fetchRequest setPredicate:predicate];
devices = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
Try this,
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"selectedRow = %#" , [NSNumber numberWithInt: selectedRowNumber]];
[fetchRequest setPredicate:predicate];
devices = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
there seems to be two problems.
I think you need to put [fetchRequest setPredicate:predicate]; before devices = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
Also #"selectedRow == %d" seems not right. You may want to change it to #"selectedRow = %d"
And no need to set entity again.
So the code may look like this.
- (void)fetchDevices {
int selectedRowNumber = 1;
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Songs"];
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"selectedRow = %d" , selectedRowNumber];
[fetchRequest setPredicate:predicate];
NSArray *devices = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
}
Let me know how it goes :)
There is no need of setting Entity using setEntity.
[fetchRequest setPredicate:predicate]
Just set predicate, it will work.
- (void)fetchDevices {
// Fetch the devices from persistent data store
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Songs"];
// retrive the objects with a given value for a certain property
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"selectedRow == %#" , selectedRowNumber];
[fetchRequest setPredicate:predicate];
devices = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[fetchRequest setPredicate:predicate];
}

Strange NSPredicate Behaviour?

Currently, I have a table view which is populated by video objects depending on the date they were recorded which was taken by using [nsdate date]; when they were recorded and saved. However, it is possible to record multiple videos in one day. I sort them by the date, and when there is more than one video with the same date, it displays the first one recorded on that date, with the most recent ones following in ascending order according to the most recent. I'm not sure why this happens but would like to check if there are more than one videos with the same date recorded, it organizes them by title. In SQL I could do something like:
ORDER BY DATE_RECORDED, TITLE ASC
Here is what I am currently doing:
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
_managedObjectContext = [appDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"whosVideo == %#", _currentPerson];
[request setPredicate:predicate];
NSEntityDescription *eval = [NSEntityDescription entityForName:#"Video" inManagedObjectContext:_managedObjectContext];
[request setEntity:eval];
NSSortDescriptor *sortDescriptor =
[[NSSortDescriptor alloc] initWithKey:#"date_recorded"
ascending:NO
selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[_managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil){
//handle error
}
[self setVideoArray:mutableFetchResults];
[self.tableView reloadData];
How would I handle adding a second predicate if there is more than one object recorded on the same date?
If you want to handle more than one predicate than you have to use NSCompoundPredicate try like this below:-
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:#"whosVideo == %#", _currentPerson];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:#"whosVideo == %#", _someOther];
NSArray *subPredicates = [[NSArray alloc] initWithObjects:predicate1, predicate2,nil];
NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];

Resources