Core-Data NSFetchedResultsController 对多关系

Posted

技术标签:

【中文标题】Core-Data NSFetchedResultsController 对多关系【英文标题】:Core-Data NSFetchedResultsController to-many relationship 【发布时间】:2013-10-07 08:11:11 【问题描述】:

这是我的数据模型:

我用数据填充了数据库。

现在我想在表格视图中显示它。 首先,我想选择具有“天”属性的一天,然后学习它的课程。 我想在标题中显示属性 'end' 和 'start' (-(NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section)

然后我想在右侧部分显示课程数据。如何使用 NSFetchedResultsController 做到这一点?

我已经设置了基本代码:

NSFetchRequest* fetch = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([Lessons class])];

NSSortDescriptor* sortGroup = [NSSortDescriptor sortDescriptorWithKey:@"lesson" ascending:YES];
fetch.sortDescriptors = @[sortGroup];

NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];

NSError* error;
[controller performFetch:&error];
if (error) 
    NSLog(@"Error: %@", error);
    abort();

编辑:

这是故事板:

更新

这是我的代码:

TableView.m(重要方法)

-(id)init

    self = [super init];
    if (self) 
        NSLog(@"%s",__PRETTY_FUNCTION__);
        self.del = [[UIApplication sharedApplication] delegate];
        self.managedObjectContext = self.del.managedObjectContext;

        NSFetchRequest* fetch = [NSFetchRequest fetchRequestWithEntityName:@"Lessons"];

        NSString *theSelectedDay = @"Mi";

        NSPredicate *pred = [NSPredicate predicateWithFormat:@"lessonToDay.day == %@", theSelectedDay];
        fetch.predicate = pred;
        NSSortDescriptor *sortTime = [NSSortDescriptor sortDescriptorWithKey:@"lessonToTime.start" ascending:YES];
        //NSSortDescriptor *sortGroup = [NSSortDescriptor sortDescriptorWithKey:@"lesson" ascending:YES];
        fetch.sortDescriptors = @[sortTime];

        self.controller = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch
                                                              managedObjectContext:self.managedObjectContext
                                                                sectionNameKeyPath:@"lessonToTime.start"
                                                                         cacheName:nil];
    
    return self;


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    // Return the number of sections.
    return 1;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    // Return the number of rows in the section.
    return 1;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath


    static NSString *CellIdentifier = @"Cell";


    // Configure the cell...
    //UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (!cell) 
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    


    Lessons *lesson = [self.controller objectAtIndexPath:indexPath];
    cell.textLabel.text = lesson.lesson;


    return cell;


- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 

    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.controller sections] objectAtIndex:section];
    // This is the first lesson in this section:
    Lessons *lesson = [sectionInfo objects][0];

    //For testing I changed the type of 'start' and 'end' to string
    NSLog(@"start: %@",lesson.lessonToTime.start);
    NSLog(@"end: %@", lesson.lessonToTime.end );

    NSString *title = [NSString stringWithFormat:@"%@-%@",
                       lesson.lessonToTime.start,
                       lesson.lessonToTime.end];
    return title;

结果:

【问题讨论】:

通常,您使用sectionNameKeyPath: 参数将表格视图分组为多个部分。但是您的要求并不清楚:如果 A 课来自 9-11,B 课来自 9-10,C 课来自 10-11,该怎么办?这些应该如何分组,部分标题应该是什么? @MartinR 给出了时间。总是这样:9-10=>第A课,第B课; 10-11=>第 C 课、第 D 课、第 E 课、第 F 课……我希望现在清楚了。 “天”实体是否描述一天,例如星期一还是星期二?我只是想知道复数形式。 这是一个错误。它描述了一天。 【参考方案1】:

首先你必须添加一个谓词,只显示所选日期的课程:

NSPredicate *pred = [NSPredicate predicateWithFormat:@"lessonToDay.day == %@", theSelectedDay];
fetch.predicate = pred;

要将表格视图分组为多个部分,您必须设置 sectionNameKeyPath: 参数 获取的结果控制器,例如@"lessonToTime.start"。这将组 所有具有相同开始时间的课程都归为一个部分。 (据我了解您的评论,具有相同开始时间的课程也具有相同的结束时间, 所以这应该足够了。) 必须使用相同的键路径作为第一个排序描述符:

NSSortDescriptor *sortTime = [NSSortDescriptor sortDescriptorWithKey:@"lessonToTime.start" ascending:YES];
NSSortDescriptor *sortGroup = [NSSortDescriptor sortDescriptorWithKey:@"lesson" ascending:YES];
fetch.sortDescriptors = @[sortTime, sortGroup];

NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch
            managedObjectContext:self.managedObjectContext
            sectionNameKeyPath:@"lessonToTime.start"
            cacheName:nil];

要根据您的需要显示节标题,您必须覆盖titleForHeaderInSection:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section  
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.controller sections] objectAtIndex:section];
    // This is the first lesson in this section:
    Lesson *lesson = [sectionInfo objects][0];
    // Now build some title from lesson.lessonToTime.start and lesson.lessonToTime.end:
    NSString *title = ...;
    return title;

【讨论】:

它无法正常工作。我已经在更新部分发布了我的代码。我做错了什么? 你实现了numberOfSectionsInTableView:numberOfRowsInSection:完全错误。返回一个固定值1 没有任何意义。 NSFetchedResultsController 文档包含如何正确实现数据源方法的示例代码。 - 也许阅读像raywenderlich.com/999/…这样的教程。 我知道像1 这样的固定值是错误的。但是为了测试它,我已经这样做了。当我在 numberOfSectionsInTableView: return self.controller.section.count 中这样实现它时,它有 0 个部分。所以访问课程的语法是错误的。 (与NSFetchedResultsController 还有更多错误,例如你不打电话给performFetch。如果您需要为插入/删除/修改的对象自动更新表视图,则必须设置 FRC 委托并实现 NSFetchedResultsControllerDelegate 方法。 - 我真的建议阅读一些教程,或者研究工作示例代码。 感谢磨坊!现在它正在工作。我只忘记了performFetch 方法。【参考方案2】:

您可以使用两个视图控制器来做到这一点:

DaysViewController - 在这里你展示了所有的日子。当用户选择单元格时,您将获得与该单元格关联的日期并将其传递给第二个视图控制器, LessonsViewController - 在这里,您在构建 NSFetchRequestpredicate 时使用传递的对象

更新:我的答案不再正确,因为问题的描述已经改变。

【讨论】:

感谢您的回答。我编辑了我的问题,添加了故事板。在顶部,用户可以选择一天。

以上是关于Core-Data NSFetchedResultsController 对多关系的主要内容,如果未能解决你的问题,请参考以下文章

在单个 NSTableView (Core-Data) 中显示来自多个实体的数据

IOS/Core-Data:添加多对多关系

从 Core-Data 请求不同的 NSManagedObject 属性实例时返回啥类?

Core-Data:如何在一个关系中保存一个对象两次

IOS/objective-c/core-data:如何从相关实体获取属性

.net core 基于Dapper 的分库分表开源框架(core-data)