核心数据 - 在多对多关系更改属性中的对象之后更新UI

时间:2014-01-03 23:05:02

标签: ios iphone objective-c core-data nsfetchedresultscontroller

我有一个核心数据模型,如下所示:

Author
======
- name
- bio

- books (to-many relationship)


Book
====
- title
- release date

- author (to-one relationship)  

我向用户呈现作者的表格视图,每个表格单元格代表作者,并显示他撰写的最新书籍的nametitle

要显示作者列表,我使用NSFetchedResultsController并使用以下NSFetchRequest

NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Author"];
request.predicate = nil;
request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];
request.fetchBatchSize = 20;  

我的问题是:

我让用户在另一个屏幕上更改书名,我希望如果用户更改了最新书的标题,则作者表视图将更新并反映最近的更改。

如何在我的作者表视图中更新最新的书名?

3 个答案:

答案 0 :(得分:2)

如果您已经在视图控制器中嵌入了NSFetchedResultController并实现了所有委托方法(请参阅前面发布的Duncan的答案),那么:

  1. 您订阅了VC上下文更改通知(viewDidLoadinit

    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(contextUpdated:)                          
                                                 name:NSManagedObjectContextObjectsDidChangeNotification
                                               object:nil];
    
  2. 实施contextUpdated方法

    -(void)contextUpdated:(NSNotification*)notification
    {
    // if the context changed on other screens
        NSManagedObjectContext *changedContext = notification.userInfo[@"managedObjectContext"];
        if ([changedContext isEqual: self.fetchedResultsController.managedObjectContext]){
            [_tableView reloadData];
        }
    }
    
  3. 请务必从通知中取消订阅您的VC

    -(void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    

答案 1 :(得分:0)

在tableViewController中实现fetchedResultsController委托方法,更新应自动反映在tableView中。

https://developer.apple.com/library/ios/documentation/CoreData/Reference/NSFetchedResultsControllerDelegate_Protocol/Reference/Reference.html

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
    atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                            withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                             withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
    atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
    newIndexPath:(NSIndexPath *)newIndexPath {

    UITableView *tableView = self.tableView;

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                       withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                       withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath]
                  atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                       withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                       withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];
}

答案 2 :(得分:0)

我的解决方案:添加一个名为&#34; triggerUpdate&#34;的布尔字段实体作者,其他名称和类型也可以;如果你更新作者写的书,只需这样设置,

author.triggerUpdate = @(!author.triggerUpdate.boolValue); 

原因是,作者更新的任何字段都会触发NSFetchedResultsChangeUpdate类型的通知。

通过这种方式,我解决了这个问题。如果你有更好的答案,请告诉我。