开发者

How do I count the number of child entities with a specific value?

I have 2 entities in a to-many relationship, Parent-->Child. The Child entity has an boolean attribute which can be TRUE or FALSE.

I can easily count how many child entities there are with [parent.child count], which returns a nice integer for me.

But what if I only want to count the child entities that are TRUE? Is there an easy way to do this?


EDIT

I've tried to implement @unforgiven's predicate selection, but I'm getting an 'unable to parse the format string' error - this is the code I'm trying (where Checklist is the parent entity, ChecklistItem is the child entity, and checked is the bool value for the ChecklistItem):

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    Checklist *aChecklist = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = aChecklist.name;

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Checklist" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SUBQUERY(checklistItem, $sub, $sub.checked == %@).@count", [NSNumber numberWithBool:YES]];
    [fetchRequest setPredicate:predicate];

    NSError *error = nil;
    NSArray *results = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

    cell.detailTextLabel.text = [NSString stringWithFormat:@"%i items ticked", [results count]];
    [fetchRequest release];
}

If I replace the p开发者_如何学JAVAredicate with any self.checklistItems.checked = %@ the the app doesn't crash, but the number returned is the total number of Checklists that have any ChecklistItem checked, which obviously means it returns the same number for every checklist.


Try getting a subset of only objects that are checked

NSPredicate *filterPredicate = [NSPredicate predicateWithFormat:@"checked = YES"]
NSSet *checkedChildren = [parent.children filteredSetUsingPredicate:filterPredicate];
NSUInteger count = [checkedChildren count];

Didn't double-check this before writing it out today, but I've written similar code on numerous occasions.

Spaced out over three lines for clarity.


You need to use a subquery in Core data. Assuming that the child entity has the boolean attribute called booleanAttribute, you need to fetch objects from the parent entity, using something similar to the following predicate:

NSPredicate *predicate = [NSPredicate predicateWithFormat: @"SUBQUERY(child, $sub, $sub.booleanAttribute == %@).@count", [NSNumber numberWithBool:YES]];


I've come up with an alternative way of doing it. I've simply added an integer attribute called "numberChecked" to my parent entity ("Checklist"), and every time a ChecklistItem is ticked or unticked, I add or delete one from numberChecked.

if ([aChecklistItem checked] == [NSNumber numberWithBool:YES]) {
    NSNumber *newCheckedNumber = [NSNumber numberWithFloat:[aChecklistItem.checklist.numberChecked floatValue] +1];
    aChecklistItem.checklist.numberChecked = newCheckedNumber;
}
else if ([aChecklistItem checked] == [NSNumber numberWithBool:NO]) {
    NSNumber *newCheckedNumber = [NSNumber numberWithFloat:[aChecklistItem.checklist.numberChecked floatValue] -1];
    aChecklistItem.checklist.numberChecked = newCheckedNumber;
}

This works perfectly, but I'd still be interested to know if anyone can think of a way of doing it without having to explicitly add it to my data model.


A few years later, this is now the easy way to do it.

You can use the @sum collection operator to easily count the objects in a collection with a YES BOOL value.

[parent valueForKeyPath:@"children.@sum.checked"];

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜