NSFetchedResultsController 委托仅在第一次应用程序启动时触发方法

发布于 2025-01-04 13:36:15 字数 4598 浏览 2 评论 0原文

抱歉我的英语很糟糕。 我的 iOS 应用程序有大问题。应用程序具有由 Core Data 管理的大型数据库。我有很多 TableView 控制器来显示这些数据。数据库中的任何更改都应显示在表视图中。它可以通过实现 NSFetchedResultsController 委托协议来实现。所有的实现都像书本上一样非常简单。如果应用程序第一次在模拟器中启动,并且我在某些表中添加新条目,则成功触发下一个委托方法:

– controllerWillChangeContent:
– controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
– controllerDidChangeContent:

停止调试并再次启动应用程序后,不会触发任何列出的方法。 它们仅在执行[managementObjectContext save]操作后调用。

你有什么想法为什么会发生这种情况吗?

源代码:

//IssueProfileViewController.h class implements NSFetchedResultController delegate methods
- (NSFetchedResultsController*)fetchedResultsController{

    if (_fetchedResultsController == nil) {

        NSManagedObjectContext *managedObjectContext = self.issue.managedObjectContext;
        NSFetchRequest *aFetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"IssueHistoryItem" inManagedObjectContext:managedObjectContext];
        [aFetchRequest setEntity:entity];

        NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"created" ascending:NO];
        NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

        //NSPredicate *predicate = [[NSPredicate predicateWithFormat:@"issue == %@ && isComment == NO", self.issue] retain];

            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"issue == %@ && isComment == NO", self.issue];

        [aFetchRequest setSortDescriptors:sortDescriptors];
        [aFetchRequest setPredicate:predicate];

            NSFetchedResultsController *aFetchedResultsController = 
                [[NSFetchedResultsController alloc] initWithFetchRequest:aFetchRequest                                                                                              
                    managedObjectContext:managedObjectContext 
                    sectionNameKeyPath:nil 
                    cacheName:nil];

        [aFetchRequest release];
        //[predicate release];
        [sortDescriptors release];
        [sortDescriptor release];
            _fetchedResultsController = aFetchedResultsController;
            _fetchedResultsController.delegate = self;
        }

        return _fetchedResultsController;
    }


-(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 {

    NSArray *paths;
//  NSIndexSet *section = [NSIndexSet indexSetWithIndex:[newIndexPath section]];

    NSIndexPath *cellContentIndexPath;

    switch (type) {
        case NSFetchedResultsChangeInsert:
//          paths = [NSArray arrayWithObject:newIndexPath];
            if (![anObject isKindOfClass:[ChangeIssueDimensionValueHistoryItem class]]) {
                cellContentIndexPath = [NSIndexPath indexPathForRow:newIndexPath.row inSection:newIndexPath.section];
                paths = [NSArray arrayWithObject:cellContentIndexPath];
                [self.tableView insertRowsAtIndexPaths:paths 
                                      withRowAnimation:UITableViewRowAnimationFade];

                [self sendMessageAboutObjectsCountChanged];
            }

            break;
        case NSFetchedResultsChangeDelete:
            paths = [NSArray arrayWithObject:indexPath];
            [self.tableView deleteRowsAtIndexPaths:paths
                                   withRowAnimation:UITableViewRowAnimationFade];
            [self sendMessageAboutObjectsCountChanged];
            break;
        case NSFetchedResultsChangeMove:
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                                        withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                                        withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeUpdate:
            [self configureCell:[self.tableView cellForRowAtIndexPath:indexPath] 
           withIssueHistoryItem:[self.fetchedResultsController objectAtIndexPath:indexPath]];
            break;
        default:
            break;
    }

}

Sorry for my terrible english.
I have big problem in my iOS app. Application has big database which is managed by Core Data. And I have many TableView Controllers for displaying this data. Any change in database should be shown in tableview. It can be reached by implementing NSFetchedResultsController delegate protocol. All realization are very simple like in books. If application starts in simulator first time and I add new entries in some tables next delegate methods are successfully fired:

– controllerWillChangeContent:
– controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
– controllerDidChangeContent:

After stop debugging and start application again none of listed methods are fired.
They calls only after [managedObjectContext save] operation will perform.

Have you any ideas why this happens?

Source code:

//IssueProfileViewController.h class implements NSFetchedResultController delegate methods
- (NSFetchedResultsController*)fetchedResultsController{

    if (_fetchedResultsController == nil) {

        NSManagedObjectContext *managedObjectContext = self.issue.managedObjectContext;
        NSFetchRequest *aFetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"IssueHistoryItem" inManagedObjectContext:managedObjectContext];
        [aFetchRequest setEntity:entity];

        NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"created" ascending:NO];
        NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

        //NSPredicate *predicate = [[NSPredicate predicateWithFormat:@"issue == %@ && isComment == NO", self.issue] retain];

            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"issue == %@ && isComment == NO", self.issue];

        [aFetchRequest setSortDescriptors:sortDescriptors];
        [aFetchRequest setPredicate:predicate];

            NSFetchedResultsController *aFetchedResultsController = 
                [[NSFetchedResultsController alloc] initWithFetchRequest:aFetchRequest                                                                                              
                    managedObjectContext:managedObjectContext 
                    sectionNameKeyPath:nil 
                    cacheName:nil];

        [aFetchRequest release];
        //[predicate release];
        [sortDescriptors release];
        [sortDescriptor release];
            _fetchedResultsController = aFetchedResultsController;
            _fetchedResultsController.delegate = self;
        }

        return _fetchedResultsController;
    }


-(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 {

    NSArray *paths;
//  NSIndexSet *section = [NSIndexSet indexSetWithIndex:[newIndexPath section]];

    NSIndexPath *cellContentIndexPath;

    switch (type) {
        case NSFetchedResultsChangeInsert:
//          paths = [NSArray arrayWithObject:newIndexPath];
            if (![anObject isKindOfClass:[ChangeIssueDimensionValueHistoryItem class]]) {
                cellContentIndexPath = [NSIndexPath indexPathForRow:newIndexPath.row inSection:newIndexPath.section];
                paths = [NSArray arrayWithObject:cellContentIndexPath];
                [self.tableView insertRowsAtIndexPaths:paths 
                                      withRowAnimation:UITableViewRowAnimationFade];

                [self sendMessageAboutObjectsCountChanged];
            }

            break;
        case NSFetchedResultsChangeDelete:
            paths = [NSArray arrayWithObject:indexPath];
            [self.tableView deleteRowsAtIndexPaths:paths
                                   withRowAnimation:UITableViewRowAnimationFade];
            [self sendMessageAboutObjectsCountChanged];
            break;
        case NSFetchedResultsChangeMove:
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                                        withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                                        withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeUpdate:
            [self configureCell:[self.tableView cellForRowAtIndexPath:indexPath] 
           withIssueHistoryItem:[self.fetchedResultsController objectAtIndexPath:indexPath]];
            break;
        default:
            break;
    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谷夏 2025-01-11 13:36:15

这似乎是 NSFetchedResultsController 执行的正确方式——响应模型层的更改(即 [managedObjectContext save])。

在文档中:https://developer. apple.com/library/ios/#documentation/CoreData/Reference/NSFetchedResultsController_Class/Reference/Reference.html 下的“响应” to Changes' 表示控制器在托管对象的上下文收到 processPendingChanges 消息之前不会显示更改。该消息也可以手动触发。

That seems to be the proper way that the NSFetchedResultsController performs--responding to changes at the model layer (i.e. [managedObjectContext save]).

In the documentation: https://developer.apple.com/library/ios/#documentation/CoreData/Reference/NSFetchedResultsController_Class/Reference/Reference.html under 'Responding to Changes' it states that the controller will not show changes until the managed object's context has received a processPendingChanges message. That message can be triggered manually, also.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文