如何计算具有特定值的子实体的数量?

时间:2011-04-06 17:41:42

标签: iphone cocoa-touch core-data parent-child

我有两个多对多关系的实体,父母 - >儿童。 Child实体有一个布尔属性,可以是TRUE或FALSE。

我可以很容易地计算[parent.child count]有多少子实体,它为我返回一个很好的整数。

但是,如果我只想计算真实的子实体呢?有一个简单的方法吗?


修改

我试图实现@unforgiven的谓词选择,但我得到了'无法解析格式字符串'错误 - 这是我正在尝试的代码(其中Checklist是父实体, ChecklistItem是子实体,checked是ChecklistItem的bool值:

- (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];
}

如果我用any self.checklistItems.checked = %@替换谓词,应用程序不会崩溃,但返回的数字是检查了任何ChecklistItem的检查表总数,这显然意味着它返回每个清单都有相同的编号。

4 个答案:

答案 0 :(得分:2)

尝试仅获取已检查对象的子集

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

今天在写出来之前没有仔细检查过,但我在很多场合都写过类似的代码。

为了清晰起见,

划出三条线。

答案 1 :(得分:0)

您需要在Core数据中使用子查询。假设子实体具有名为booleanAttribute的布尔属性,您需要使用类似于以下谓词的东西从父实体获取对象:

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

答案 2 :(得分:0)

我想出了另一种方法。我只是向我的父实体(“Checklist”)添加了一个名为“numberChecked”的整数属性,每次勾选或取消勾选ChecklistItem时,我都会从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;
}

这很有效,但我仍然有兴趣知道是否有人可以想到一种方法,而不必明确地将其添加到我的数据模型中。

答案 3 :(得分:0)

几年后,现在这是一个简单的方法。

您可以使用@sum collection operator轻松计算集合中具有YES BOOL值的对象。

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