我有两个实体:患者和工作。患者与Job有很多关系称为“工作”,Job与患者有一对一的关系称为“患者”。 Job有'dueDate'(Date)和'completed'(BOOL)属性,Patient有'firstName'和'lastName'属性(两个字符串)。
我正在尝试为我的NSFetchedResultsController创建一个获取请求/谓词,我们抓取所有尚未完成的作业(即已完成==否)并按患者姓名划分它们。这是我的代码:
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];
这似乎不起作用。我是以错误的方式解决这个问题吗?
答案 0 :(得分: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]
的电话回来了什么?在此处设置一个断点并检查该值并确保您返回NSManagedObject
而不是nil。在该方法中设置断点也将确认您正在被调用。
您的secondKeypathName将无法正常工作。您可能希望将其设置为@"patient.lastName"
,以便它与我上面描述的初始排序相匹配。
您的-tableView: titleForHeaderInSection:
应该访问NSFetchedResultsController
提供的缓存,而不是假设该部分中会有一行:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
id sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo name];
}
最后,如果您希望该部分真正显示“姓氏,名字”格式,那么您需要在Patient
实体上创建非瞬态派生值属性fullName
,以便您可以根据它创建缓存。然后,只要更改了名字或姓氏,就需要更新此派生值。
答案 1 :(得分:3)
首先,您似乎没有将sortDescriptors附加到fetchRequests。这可能与问题有关,也可能没有。
其次,您可以更轻松地完成此任务。像这样:
sectionNameKeyPath:@"patient.name"
“name”应该是Patient对象的属性或方法。实现这一目标的一种简单方法是对患者采用分类方法:
- (NSString *)name {
return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}
实际上,你无法通过这样简单的事情来实现你的目的,请阅读mzarra的答案以获得正确答案。 NSFetchedResultsController有这个批评意见:
如果控制器生成节,则数组中的第一个排序描述符用于将对象分组为多个节;它的键必须与sectionNameKeyPath相同,或者使用其键的相对排序必须与使用sectionNameKeyPath匹配。
但是,你不能对方法调用的结果进行排序,你需要一个对象的属性。所以,你最好的选择可能只是在“病人”上有一个“名字”属性,并使用该属性进行排序和sectionNameKeyPath。
答案 2 :(得分:2)
除了不将sortDescriptors分配给fetchRequest之外,我相信你的谓词有问题。由于您正在处理Core Data,因此“completed”属性的布尔值存储在NSNumber的实例中。类似下面的谓词会更好:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"completed = %@", [NSNumber numberWithBool:NO]];