向关系中插入新数据时如何更新tableView

Posted

技术标签:

【中文标题】向关系中插入新数据时如何更新tableView【英文标题】:how to update tableView when insert new data to the relation 【发布时间】:2012-12-11 21:14:30 【问题描述】:

我使用 2 个实体 Person 和 Event,它们通过关系“事件”一对多连接。在我的第一个表格视图中,我有人的名字,第二个我有他们的事件类型。我可以将新事件插入特定的人,但第二个表格视图也没有更新的问题。只有当我使用导航器返回人员并且在它再次发生事件之后我才能看到更改。

插入新事件我使用这个方法:

- (void) addEventControllerDidSave:(NSString *)typeData

    NSManagedObjectContext* context = [self managedObjectContext];
    Event *newEvent = (Event *)[NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:context];
    [newEvent setType:typeData];
    [currentPerson addEventsObject:newEvent];

    NSError *error;
    if (![[self managedObjectContext] save:&error])
    
        NSLog(@"Problem saving: %@", [error localizedDescription]);
    

    [self dismissViewControllerAnimated:YES completion:nil];

我如何定义单元格:

//create cell use relation
    NSArray *eventsArray = [[[[self currentPerson] events] objectEnumerator]allObjects];
    Event *newEvent = [eventsArray objectAtIndex:indexPath.row];
    [[cell textLabel]setText: [newEvent type]];

更新表方法:

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


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


- (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:
        
            NSArray *eventsArray = [[[[self currentPerson] events] objectEnumerator]allObjects];
            Event *newEvent = [eventsArray objectAtIndex:indexPath.row];
            UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
            [[cell textLabel]setText: [newEvent type]];
            break;
        
        case NSFetchedResultsChangeMove:
        
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
        
        default:
            break;
    //switch


- (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;
        default:
            break;
    

我真的不知道如何正确更新 tableView,我更新了我的第一个 tableView 但第二个有我早期描述的问题(可能是因为我使用关系?) 您还可以在 git 上看到我的完整项目(也许有帮助):

https://github.com/dennis87/eventCost

【问题讨论】:

【参考方案1】:

EventsTableController 有一个fetchResultsController 属性和对应的_fetchResultsController 实例变量。但是这个 FRC 始终是 nil,因为它从未在 EventsTableController 中分配 + 初始化。

更新方法 controllerWillChangeContentdidChangeObjectcontrollerDidChangeContent 永远不会被调用,因为您没有带委托的 FRC。

作为一种解决方法,您可以添加

[self.tableView reloadData];

addEventControllerDidSave 中,新条目将立即可见。

但真正的解决方案是初始化并使用 FRC,就像您在 NamesTableController 中所做的那样。然后会自动显示新事件。


创建一个获取当前人员的所有事件的获取结果控制器如下所示(这是您来自 NamesTableController 的代码,已修改为在 EventsTableController 中使用):

-(NSFetchedResultsController *) fetchResultsController
    if (_fetchResultsController != nil) 
        return _fetchResultsController;
    

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event"
                                              inManagedObjectContext:[self managedObjectContext]];
    [fetchRequest setEntity:entity];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"person = %@", self.currentPerson];
    [fetchRequest setPredicate:predicate];

    NSSortDescriptor *sort = [[NSSortDescriptor alloc]initWithKey:@"type" ascending:YES];
    NSArray *sortArray = [[NSArray alloc]initWithObjects:sort, nil];
    [fetchRequest setSortDescriptors:sortArray];

    _fetchResultsController = [[NSFetchedResultsController alloc]
                               initWithFetchRequest:fetchRequest
                               managedObjectContext:[self managedObjectContext]
                               sectionNameKeyPath:nil
                               cacheName:nil];

    _fetchResultsController.delegate = self;
    return _fetchResultsController;

【讨论】:

再次感谢!,我把这行synthesize fetchResultsController = _eventsFetchResultsController;和我的namesTableController中的方法当然我将_NFC更改为_eventsNFC..实体和属性但我仍然有这个问题,我做错了什么? @Dennis:NamesTableController 有一个方法-(NSFetchedResultsController *) fetchResultsController,其中 FRC 是使用获取请求和排序描述符创建的。 - 您必须在为事件创建 FRC 的 EventsTableController 中添加类似的方法。 这正是我所做的,正如您在我在这里所做的新提交中看到的那样:github.com/dennis87/eventCost/commit/…(cmets 简称)但由于某种原因这不起作用。 @Dennis:我会看看,但不会在今晚(德国时间)之前 - 你不要使用表格视图数据源方法中的 FRC numberOfRowsInSectioncellForRowAtIndexpath,...! 只是为了了解我需要在此方法中使用 FRC,因为 FRC 已更新,然后我的 tableView 也会更新,对吗?但是当我创建新事件时,我使用以下代码: [currentPerson addEventsObject:newEvent];我的新事件对象保存在“事件”关系中?或者只是一些知道将关系与事件联系起来的索引?当我创建 FRC 时,我需要使用哪些实体和属性?事件和类型?

以上是关于向关系中插入新数据时如何更新tableView的主要内容,如果未能解决你的问题,请参考以下文章

向 SQLite 后端添加内容时更新表

如何在不插入新对象的情况下从数据库更新对象?

当新数据插入 MySQL 数据库时,如何自动更新 recyclerView?

将数据从一个表插入到一个单列另一个没有关系的表

如何在 NSMutableArray 中插入新行?

如何在 Swift 中向实体插入新数据?