NSFetchedResultsController 与 NSSortDescriptor 一对一

Posted

技术标签:

【中文标题】NSFetchedResultsController 与 NSSortDescriptor 一对一【英文标题】:NSFetchedResultsController with NSSortDescriptor one to one 【发布时间】:2017-03-22 06:44:28 【问题描述】:

想要在NSFetchedResultsController 中使用NSSortDescriptor 按具有一对一关系的名称排序。这是我的代码

NSFetchRequest <studentDetail *> *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[studentDetail entityName]];

NSSortDescriptor *sortDescriptorForSchoolName = [NSSortDescriptor sortDescriptorWithKey:NSStringFromSelector(@selector(schoolName))
                                                                             ascending:YES
                                                                              selector:@selector(localizedCaseInsensitiveCompare:)];

NSSortDescriptor *sortDescriptorForSchool = [NSSortDescriptor sortDescriptorWithKey:NSStringFromSelector(@selector(school))
                                                                               ascending:YES];

[fetchRequest setSortDescriptors:@[sortDescriptorForSchool, sortDescriptorForSchoolName]];

[fetchRequest setFetchBatchSize:4];

NSManagedObjectContext *mainContext = [[coreDataManager sharedManager] managedObjectContext];

NSFetchedResultsController *FRC = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                                                       managedObjectContext:mainContext
                                                                                         sectionNameKeyPath:nil
                                                                                                  cacheName:nil];

[FRC setDelegate: self];

NSError *fetchError = nil;

if (![FRC performFetch: &fetchError])
    NSLog(@"fetch error: %@", fetchError);

[self setStudentDetailFetchedResultsController: FRC];

示例数据库格式:

    学校和学生是实体名称。 学校与学生的一对多关系。 共有 4 所学校。每所学校有 4 名学生。 现在我想按姓名升序显示所有学生列表。

UITableView 我正在显示学生的详细信息。可以选择按school 实体对学生进行排序。在我的 FRC 中有studentDetail。如何使用 FRC 对这些细节进行排序?

来自studentDetail 的实体与school 具有一对一的关系。

更新

school entity一对多

school1
 relationship
    ->student1
    ->student2
    ->student3
    ->student4
school2
 relationship
    ->student5
    ->student6
    ->student7
    ->student8
school3
 relationship
    ->student9
    ->student10
    ->student11
    ->student12
school4
 relationship
    ->student13
    ->student14
    ->student15
    ->student16

student entity 一对一

    student1
 relationship
    ->school1
student2
 relationship
    ->school1
student3
 relationship
    ->school1
student4
 relationship
    ->school1
student5
 relationship
    ->school2
student6
 relationship
    ->school2
student7
 relationship
    ->school2
student8
 relationship
    ->school2
student9
 relationship
    ->school3
student10
 relationship
    ->school3
student11
 relationship
    ->school3
student12
 relationship
    ->school3
student13
 relationship
    ->school4
student14
 relationship
    ->school4
student15
 relationship
    ->school4
student16
 relationship
    ->school4

Got answer from 感谢@RunLoop。但这需要我想要的一些改变。

正如我在代码中提到的对NSStringFromSelector(@selector(school)) 进行排序,例如:[NSSortDescriptor sortDescriptorWithKey[NSString stringWithFormat:@"%K.%K", NSStringFromSelector(@selector(school)), NSStringFromSelector(@selector(schoolName))] ascending:YES] 而不是[NSSortDescriptor sortDescriptorWithKey:@"school.schoolName" ascending:YES]

如果我使用这种方法,在功能中,如果我更改实体中的任何名称,它会显示警告,而静态的 school.schoolName 则不会。那可能吗? 我用NSPredicate 尝试了这种方法,但没有显示任何警告。我该如何解决这个问题?

【问题讨论】:

您要数据库值还是数据库流程图? @RunLoop 你现在可以检查吗?更新的问题。如果我在这里错过任何评论。 【参考方案1】:

以下代码将获取学生,按 schoolName 然后按 studentName 排序:

NSFetchRequest *fr = [NSFetchRequest fetchRequestWithEntityName:@"Student"];
NSSortDescriptor *schoolNameSD = [NSSortDescriptor sortDescriptorWithKey:@"school.schoolName" ascending:YES];
NSSortDescriptor *studentNameSD = [NSSortDescriptor sortDescriptorWithKey:@"studentName" ascending:YES];
fr.sortDescriptors = @[schoolNameSD, studentNameSD];

NSManagedObjectContext *moc = [[coreDataManager sharedManager] managedObjectContext];


NSFetchedResultsController *frc = [[NSFetchedResultsController alloc] initWithFetchRequest:fr
                                                                          managedObjectContext:moc
                                                                            sectionNameKeyPath:nil
                                                                                     cacheName:nil];
[frc performFetch:nil];

如果您只想按 studentName 排序,只需删除 schoolNameSD 并让 frc 再次执行提取。

【讨论】:

感谢@RunLoop。有效!!!实际上我之前尝试过这个,当时这个方法不起作用。但我想像这样使用NSStringFromSelector(@selector(schoolName)) 格式。我尝试使用 NSString 并收到警告。 [NSString stringWithFormat:@"%K.%K", NSStringFromSelector(@selector(school)), NSStringFromSelector(@selector(schoolName))] 警告Invalid conversion specifier K。如果我使用这种方法,在功能中如果我更改实体中的任何名称,它会显示警告和静态一个 school.schoolName 不是这就是为什么,你能帮忙解决这个问题吗? 嗨,很高兴我能帮上忙。请点击 ✓ 将我的答案标记为正确。您不应使用选择器指定排序键。如果您想执行不同的排序,请为 frc 分配一个新的排序描述符并要求它使用。 不,不是另一种相同的。我将标记为正确的,但我仍然需要使用另一种格式的确切格式,我也发布类似这种格式的问题。 [NSSortDescriptor sortDescriptorWithKey[NSString stringWithFormat:@"%K.%K", NSStringFromSelector(@selector(school)), NSStringFromSelector(@selector(schoolName))] ascending:YES] 而不是 [NSSortDescriptor sortDescriptorWithKey:@"school.schoolName" ascending:YES] 这个给 Waring Invalid conversion specifier K。我试图找出自己(在发布这个问题之前),但我无法得到我想要的。 当一个问题被回答后,它被标记为正确。后续问题应作为新问题而不是附加问题放入 cmets。 我想遵循编码结构,这就是为什么我仍在等待与NSStringFromSelector 进行排序的原因,这不是新问题,它就像子问题一样。我会更新问题。

以上是关于NSFetchedResultsController 与 NSSortDescriptor 一对一的主要内容,如果未能解决你的问题,请参考以下文章

在 Core Data 应用程序中调用 performFetch 后,是不是需要手动更新表视图?