2

我有两个实体:Patient 和 Job。Patient 与 Job 的一对多关系称为“jobs”,而 Job 与 Patient 的一对一关系称为“patient”。Job 具有名为“dueDate”(日期)和“完成”(BOOL)的属性,而 Patient 具有属性“firstName”和“lastName”(均为字符串)。

我正在尝试为我的 NSFetchedResultsController 创建一个获取请求/谓词,我们将抓取所有尚未完成的作业(即已完成 == NO)并按患者姓名对其进行分段。这是我的代码:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Job" inManagedObjectContext:moc];
[fetchRequest setEntity:entity];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(completed == NO)"];
[fetchRequest setPredicate:predicate];

NSSortDescriptor *patientDescriptor = [[NSSortDescriptor alloc] initWithKey:@"patient" ascending:YES];
NSSortDescriptor *dueDateDescriptor = [[NSSortDescriptor alloc] initWithKey:@"dueDate" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:patientDescriptor, dueDateDescriptor, nil];

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:moc sectionNameKeyPath:@"patient" cacheName:@"Jobs"];

这是我的 titleForHeaderInSection 方法:

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:section];
NSString *firstName = [[(Job *)[fetchedResultsController objectAtIndexPath:indexPath] patient] firstName];
NSString *lastName = [[(Job *)[fetchedResultsController objectAtIndexPath:indexPath] patient] lastName];

return [NSString stringWithFormat:@"%@ %@", firstName, lastName];

这似乎不起作用。我会以错误的方式解决这个问题吗?

4

3 回答 3

6

它怎么不工作?它有助于描述您所看到的结果。

您没有将排序描述符添加到您的 NSFetchRequest,至少在您提供的示例中。

您的排序描述符无效。这似乎Patient是一种关系,因此对关系进行排序将不起作用。你会想要做如下的排序:

NSSortDescriptor *lastNameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"patient.lastName" ascending:YES];
NSSortDescriptor *firstNameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"patient.firstName" ascending:YES];
NSSortDescriptor *dueDateDescriptor = [[NSSortDescriptor alloc] initWithKey:@"dueDate" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects: lastNameDescriptor, firstNameDescriptor, dueDateDescriptor, nil];

[fetchRequest setSortDescriptors:sortDescriptors];

[lastNameDescriptor release], lastNameDescriptor = nil;
[firstNameDescriptor release], firstNameDescriptor = nil;
[dueDateDescriptor release], dueDateDescriptor = nil;

您不需要强制转换[fetchedResultsController objectAtIndexPath:indexPath],因为它返回 id。

你从电话中得到[fetchedResultsController objectAtIndexPath:indexPath]什么?在此处放置一个断点并检查该值并确保您返回的是 aNSManagedObject而不是 nil。在该方法中放置断点也将确认您正在被调用。

您的 secondKeypathName 不会像上面提到的那样工作。您可能希望将其设置为@"patient.lastName"使其与我上面描述的初始排序相匹配。

-tableView: titleForHeaderInSection:应该访问由提供的缓存,NSFetchedResultsController而不是假设该部分中将有一行:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 
{
    id sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo name];
}

最后,如果您希望该部分真正显示“姓氏,名字”格式,那么您将需要在您的实体上创建一个非瞬态派生值属性,以便您可以基于它创建缓存。然后,只要名字或姓氏发生变化,就需要更新这个派生值。PatientfullName

于 2010-03-31T16:14:18.630 回答
3

首先,您似乎没有将 sortDescriptors 附加到 fetchRequests。这可能与问题有关,也可能无关。

其次,您可以以更简单的方式完成此操作。让它像这样:

sectionNameKeyPath:@"patient.name"

“name”应该是 Patient 对象的属性或方法。实现这一点的一种简单方法是对患者使用类别方法:

- (NSString *)name {
    return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}

实际上,您无法通过这样简单的事情来实现您的目的,请阅读 mzarra 的答案以获得正确答案。NSFetchedResultsController 有这样的批判性评论:

如果控制器生成节,则数组中的第一个排序描述符用于将对象分组为节;它的键必须与 sectionNameKeyPath 相同,或者使用其键的相对顺序必须与使用 sectionNameKeyPath 的顺序匹配。

但是,您不能对方法调用的结果进行排序,您需要对象的属性。因此,您最好的选择可能是在“患者”上设置一个“名称”属性,并将该属性用于排序和 sectionNameKeyPath。

于 2010-03-31T15:53:37.400 回答
2

除了不将您的 sortDescriptors 分配给您的 fetchRequest 之外,我相信您的谓词有问题。由于您正在处理核心数据,因此“已完成”属性的布尔值存储在 NSNumber 的实例中。像下面这样的谓词会更好:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"completed = %@", [NSNumber numberWithBool:NO]];
于 2010-03-31T16:16:44.317 回答