In my ios project I use two entities (CoreData): Person and Gifts with To-Many Relationship
I know how to calculate the sum of gifts to one person:
NSDecimalNumber *orderSum=[person.gifts valueForKeyPath:#"#sum.priceOfGift"];
But how do I calculate the sum of all persons?
-(NSFetchedResultsController *) fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
//NSError *error = nil;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Person"
inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"nameOfPerson"
ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
_fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:#"nameOfGroup" cacheName:nil];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
The "sum of all persons" would be to fetch all persons and count them
int sum = fetchedObjects.count;
But perhaps you mean the "sum of the prices of all gifts of all persons". If you think about it, it is the same as the sum of the prices of all gifts. Thus, you can just fetch the gifts and calculate
NSNumber *sum = [self.fetchedResultsController.fetchedObjects
valueForKeyPath:#"#sum.priceOfGift"];
You can try to fetch all the Persons, then use the sum
NSError *error = nil;
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"Person" inManagedObjectContext:managedObjectContext];
request.predicate = nil;
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"index" ascending:YES]];//some parameter
NSArray *persons = [managedObjectContext executeFetchRequest:request error:&error];
NSDecimalNumber *orderSum;
for (Person *person in persons)
orderSum = [NSDecimalNumber decimalNumberWithDecimal:orderSum.decimalValue
+[person valueForKeyPath:#"gifts.#sum.priceOfGift"].decimalValue]
Though, now work with NSDecimalNumber look a bit uncomfortable.
Related
I am using CoreData in my application. Everything is working fine except coredata is always returning max 20 records although i have more than 50 records. I have checked my code again and again but not finding the exact reason. I am also not using fetchLimit property. Kindly Help me.
Thanks.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:_manager.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = nil;
if (key != nil) {
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:key ascending:ascending];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
}
NSError *error = nil;
NSMutableArray *array = [[_manager.managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
return array;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSInteger rowCount = [context countForFetchRequest:fetchRequest error:&error];
fetchRequest.fetchLimit = rowCount;
NSArray *allItems = [context executeFetchRequest:fetchRequest error:&error];
Here rowCount will calculate actual count of all rows and you can set it as fetchLimit
Core Data returns 20 records by default. You can set records limit by using setFetchLimit of NSFetchRequest class.
NSFetchRequest* request = [[NSFetchRequest alloc] init];
[request setEntity:[...]];
[request setFetchLimit:50];
I have stored dictionary in the transformable attribute.I want to know
How to get single data from it?**
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]
initWithEntityName:#"MemberProfile"];
NSSortDescriptor *ordering = [[NSSortDescriptor alloc] initWithKey:
[member.member_Profile objectForKey:"#order"] ascending:YES];
[fetchRequest setSortDescriptors:[NSArray
arrayWithObjects:ordering,nil]];
NSArray *result = [self.managedObjectContext
executeFetchRequest:fetchRequest error:Nil];
self.masterList = [[NSMutableArray alloc] initWithArray:result];
Import NSManagedObject(InstallProject) and fetch one object like this,
-(InstallProject *)readSelectedInstall:(NSString *)projIDString
{
NSArray *fetchedObjects;
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"InstallProject" inManagedObjectContext: context];
[fetch setEntity:entityDescription];
[fetch setPredicate:[NSPredicate predicateWithFormat:#"(ANY ProjID contains[cd] %#)",projIDString]];
NSError * error = nil;
fetchedObjects = [context executeFetchRequest:fetch error:&error];
if([fetchedObjects count] == 1)
return [fetchedObjects objectAtIndex:0];
else
return nil;
}
Consider the above model with to-many relation.
Let's assume I am querying to get managed-objects where patient first or last name is "xyz" (there are multiple records of "xyz").
How to get a unique "xyz" as dictionary object and repeated "xyz" Managed-objets as objects in that dictionary.
So far I am able to get distinct values and also I am able to get array of managed objects where "xyz" is the predicate string.
But I am unable to think of a way to get array of dictionaries with its objects as managed-objects of duplicate values.
I want to have an array of dictionaries with unique value as dictionary name and objets in dictionary should be managed-objects/dictionaries.
Could somebody please help me with this. I will provide more explanation if any part is not understood.
Thanks
#pragma mark - Search Patients By Patient Name
-(NSArray*)GetBillsForPatientwith:(NSString*)name{
NSMutableArray *AllBillsData = [[NSMutableArray alloc]init];
NSArray *_strings = [self GetSplitStrings:name];
NSManagedObjectContext *context = [CoreDataManager GetCoreDataManager].managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:_Claims inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"patient_FirstName" ascending:YES];
NSArray *sortDescriptors = #[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
NSMutableArray *subPredicates = [NSMutableArray array];
for (NSString *strings in _strings) {
[subPredicates addObject:
[NSPredicate predicateWithFormat:#"patient_FirstName CONTAINS[cd] %# OR patient_LastName contains[cd] %#",strings,strings]];
}
NSCompoundPredicate *predicate_ = [[NSCompoundPredicate alloc]initWithType:NSOrPredicateType subpredicates:subPredicates];
[fetchRequest setReturnsObjectsAsFaults:NO];
[fetchRequest setPredicate:predicate_];
fetchRequest.returnsDistinctResults = YES;
fetchRequest.resultType = NSDictionaryResultType;
fetchRequest.propertiesToFetch = [NSArray arrayWithObjects:[[entity propertiesByName] objectForKey:#"patient_FirstName"],[[entity propertiesByName] objectForKey:#"patient_LastName"], nil];
//fetchRequest.propertiesToGroupBy = [NSArray arrayWithObjects:[[entity propertiesByName] objectForKey:#"patient_FirstName"],[[entity propertiesByName] objectForKey:#"patient_LastName"], nil];
NSError *error;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
// Handle the error.
}
for (NSDictionary *names in fetchedObjects) {
// [AllBillsData addObject:names];
[AllBillsData addObject:[self GetCorrespondingClaimsForNames:names]];
}
return AllBillsData;
}
//Entangled Method
-(NSArray*)GetCorrespondingClaimsForNames:(id)Names{
NSManagedObjectContext *context = [CoreDataManager
GetCoreDataManager].managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:_Claims inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"patient_FirstName" ascending:YES];
NSArray *sortDescriptors = #[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
NSMutableArray *subPredicates = [NSMutableArray array];
[subPredicates addObject:
[NSPredicate predicateWithFormat:#"patient_FirstName ==[cd] %# AND patient_LastName ==[cd] %#",[Names valueForKey:#"patient_FirstName"],[Names valueForKey:#"patient_LastName"]]];
NSCompoundPredicate *predicate_ = [[NSCompoundPredicate alloc]initWithType:NSOrPredicateType subpredicates:subPredicates];
[fetchRequest setReturnsObjectsAsFaults:NO];
[fetchRequest setPredicate:predicate_];
NSError *error;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
// Handle the error.
}
return fetchedObjects;
}
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
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];