If I understand correctly you have to use setResultType:NSDictionaryResultType to allow setReturnsDistinctResults to work.
When I don't use setResultType:NSDictionaryResultType I don't get distinct results as expected.
When I do use it I get:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSKnownKeysDictionary1 objectID]: unrecognized selector sent to instance
I want the distinct results to populate a UITableViewCell:
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
LocationInfo *info = [_fetchedResultsController objectAtIndexPath:indexPath] ;
cell.textLabel.text = info.fieldname;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#, %#, %#",
info.date, info.acres, info.comments];
}
I'm using a simple NSFetchedResultsController with the setResultType set to NSDictionaryResultType:
NSManagedObjectContext *moc = [appDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Contacts" inManagedObjectContext:moc];
[fetchRequest setEntity:entity];
fetchRequest.propertiesToFetch = [NSArray arrayWithObject:[[entity propertiesByName] objectForKey:#"fieldname"]];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:#"fieldname" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setResultType:NSDictionaryResultType];
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:#"fieldname"]];
[fetchRequest setReturnsDistinctResults:YES];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:moc sectionNameKeyPath:nil
cacheName:#"Root"];
_fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = nil;
return _fetchedResultsController;
Am I improperly feeding the configureCell? What is the proper way to do this?
Related
I am trying to wrap my head around CoreData. So I am having a static tableview for statistics with labels like: "number of entries", "total distance", "total time" etc. I have my coredata entity called "Recording" and its attributes "startDate","duration",... and I would like to fetch all entries from the CURRENT week and then on one hand display the number of entries and on the other hand the total time. I know how to set up a fetch request (thank you, google)
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil)
{
return _fetchedResultsController;
}
if (self.managedObjectContext)
{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Recording" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"startDate" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *frc = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
frc.delegate = self;
self.fetchedResultsController = frc;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error])
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
}
return _fetchedResultsController;
}
but I am stuck with this special idea and I am not even sure if I need to do it with this...
I solved it now using:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
NSEntityDescription *theType = [NSEntityDescription entityForName:#"Recording" inManagedObjectContext:self.managedObjectContext];
fetchRequest.entity = theType;
NSDate *firstDayOfCurrentWeek = [self firstWeekday:[NSDate date]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"((startDate > %#) AND (startDate <= %#))",firstDayOfCurrentWeek, [NSDate date]];
fetchRequest.predicate = predicate;
NSSortDescriptor *theDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"startDate" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObjects:theDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
and finding the sum/total like this:
NSFetchedResultsController *fetchedResults = self.fetchedResultsController;
NSInteger allWorkouts = [[fetchedResults fetchedObjects] count];
CGFloat totalDistance = [[[fetchedResults fetchedObjects] valueForKeyPath: #"#sum.distance"] floatValue];
Thanks for the hint with the predicate :)
NSPredicate is what you're searching for.
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData/Articles/cdFetching.html
The following finds all Master objects with Master.nameLast equally a passed in string. Though I want the NSPredicate to check if the object matches Master.nameLast and if this object has Master.batting.ab > 0
- (NSFetchedResultsController *)fetchedResultsController {
if(_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext *context = [self managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Master" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"debut" ascending:YES];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"nameLast = [c]%#", nameLast];
[fetchRequest setPredicate:predicate];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
fetchRequest.sortDescriptors = sortDescriptors;
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
return _fetchedResultsController;
}
I want something that finds all Master objects matching the passed in string and have Master.batting.ab > 0
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(nameLast = [c]%#) AND (ANY batting.ab > 0)", nameLast];
The code below didn't return any objects on initial fetch, while succeeding fetch returns the right objects. I'm also checking the vehicleManagedObjectContext, but it is always empty.
- (NSArray *)getVehicleInfo {
if (vehicleManagedObjectContext == nil) {
NSLog(#"======== Error: vehicleManagedObjectContext is empty");
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"VehicleInfo" inManagedObjectContext:vehicleManagedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"vehicleType" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:vehicleManagedObjectContext sectionNameKeyPath:#"vehicleType" cacheName:nil];
[fetchedResultsController performFetch:nil];
NSLog(#"======== fetchedObjects : %#",[fetchedResultsController fetchedObjects]);
if ([fetchedResultsController fetchedObjects] && [[fetchedResultsController fetchedObjects] count] > 0) {
return [fetchedResultsController fetchedObjects];
}
return nil;
}
I'm having a fetchrequest. Now I need to get "tracked" points from the database but when there are no tracked points they all need to be retrieved.
How can I do that? I now set a predicate on my fetchcontroller but when it doesn't find any tracked points it just doesn't show anything. So where can I hook up on this and then say retrieve everything...
Is there a way to listen that there is nothing found or how is this done?
EDIT:
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Rank" inManagedObjectContext:[NSManagedObjectContext MR_defaultContext]];
[fetchRequest setEntity:entity];
/* NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", #"Auto"];
[fetchRequest setPredicate:predicate];*/
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:NO];
[fetchRequest setSortDescriptors:#[sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:[NSManagedObjectContext MR_defaultContext] sectionNameKeyPath:nil
cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
Thanks to Larme this is the solution:
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Rank" inManagedObjectContext:[NSManagedObjectContext MR_defaultContext]];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", #"DON"];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:NO];
[fetchRequest setSortDescriptors:#[sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:[NSManagedObjectContext MR_defaultContext] sectionNameKeyPath:nil
cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
if ([[_fetchedResultsController fetchedObjects] count] == 0)
{
NSLog(#"0 found");
[fetchRequest setPredicate:nil];
}
return _fetchedResultsController;
}
in my app I am sorting an entity using only one NSSortDescriptor, but now I need to filter the data for 4 different attributes. This is the code for the current sorting, the result are all records from the entity sorted by the attribute 'displayOrder', but I need to filter the records by four other attributes(year,month,day,group), all of them integer32 except group which is string :
- (NSFetchedResultsController *)fetchedResultsController
{
if (fetchedResultsController) return fetchedResultsController;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity =
[NSEntityDescription entityForName:#"FavoriteThing"
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor =
[[NSSortDescriptor alloc] initWithKey:#"displayOrder"
ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc]
initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:nil cacheName:#"ThingsCache"];
aFetchedResultsController.delegate = self;
[self setFetchedResultsController:aFetchedResultsController];
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
return fetchedResultsController;
}
I have tried adding a predicate:
NSNumber *yearSearched = 1965;
NSPredicate *yearPredicate = [NSPredicate predicateWithFormat:#"todoYear = %#", yearSearched];
[fetchRequest setPredicate:yearPredicate];
But after running the app there is an error EXC_BAD_ACCESS at the line NSPredicate *yearPredicate = [NSPredicate predicateWithFormat:#"todoYear = %#", yearSearched];
Where the attribute 'todoYear' is from type Integer32
Your NSNumber creation is wrong (you're just setting the pointer to an integer). It should be:
NSNumber *yearSearched = #1965;
NSPredicate *yearPredicate = [NSPredicate predicateWithFormat:#"todoYear = %#", yearSearched];
[fetchRequest setPredicate:yearPredicate];