NSFetchedResultsController –创建新部分时出现异常(更新:可能是删除部分中的所有行时...)

发布于 2024-10-15 02:07:20 字数 3113 浏览 3 评论 0原文

我有一个带有 TableView 和 NSFetchedResultsController 的视图。 我使用 ASINetworkQueue(NSOperationQueue 的子类)和 ASIHTTPRequest 的子类(ASIHTTPRequest 又是 NSOperation 的子类)来下载 JSON feed、解析它并将相应的实体插入到 Core Data 中。 因此,在 ASIHTTPRequest 子类中,我有第二个 NSManagedObjectContext 来保持所有内容的线程安全和良好。

一切都很好,我的后台获取/导入每 10 秒左右就会触发一次,创建新实体并将其保存到核心数据存储中。 NSNotification 将其方式传播到 ViewController 和 NSFetchedResultsController,并且新行出现在 TableView 中。

当 JSON 包含具有新节键值的实体(我们称之为“sectionID”)时,就会出现问题 - 例如,sectionID == 2 而不是sectionID == 1(明白了吗?)。

此时, NSFetchedResultsController 应该使表视图创建一个新部分,但我却遇到了异常:

Serious application error.  Exception was caught during Core Data change processing.  This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification.  *** -[NSArray initWithObjects:count:]: attempt to insert nil object at objects[0] with userInfo (null)
Assertion failed: (_Unwind_SjLj_Resume() can't return), function _Unwind_SjLj_Resume, file /SourceCache/libunwind/libunwind-24.1/src/Unwind-sjlj.c, line 326.

这是我的 NSFetchedResultsControllers 委托方法的代码:

-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{

    [[self eventTable] beginUpdates];

}

-(void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
    NSIndexSet* set = [NSIndexSet indexSetWithIndex:sectionIndex];
    switch (type) {
        case NSFetchedResultsChangeInsert:
            [[self eventTable] insertSections:set withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeDelete:
            [[self eventTable] deleteSections:set withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
    UITableView* tv = [self eventTable];
    switch (type) {
        case NSFetchedResultsChangeInsert:
            [tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeDelete:
            [tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeUpdate:
            [self tableView:tv configureCell:[tv cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;
    }
}

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

关于导致异常的原因有什么想法吗?提前致谢!

更新2011-02-03 不太确定错误是在创建新部分时发生还是在删除旧部分时发生。我几乎认为当一个部分中的所有行都被删除时会发生这种情况,但由于某种原因控制器:didChangeSection:atIndex:forChangeType没有被调用。 有人有类似经历吗?

更新2011-02-08 我想我解决了。问题是在确定是否删除行/节时必须考虑一些额外的条件。 当使用 Apple 文档中提供的代码(以及一些调整以使其在我看来有效)时,它运行正常。

I've got a view with a TableView and an NSFetchedResultsController.
I'm using a ASINetworkQueue (subclass of NSOperationQueue) and a subclass of ASIHTTPRequest (which in turn is a subclass of NSOperation) to download a JSON feed, parse it and insert corresponding entities into Core Data.
Therefore, in the ASIHTTPRequest subclass, I've got a second NSManagedObjectContext to keep everything threadsafe and nice.

Everything is fine, my background fetching/import fires of each 10 seconds or so, new entities are created and saved into the Core Data store. The NSNotification propagates its way to the ViewController and the NSFetchedResultsController and new rows appear in the TableView.

The problem occurs when the JSON contains an entity with a new value of the section key (lets call it "sectionID") – for example sectionID == 2 instead of sectionID == 1 (you get it?).

At this point, the NSFetchedResultsController should make the table view create a new section, but instead I'm getting an exception:

Serious application error.  Exception was caught during Core Data change processing.  This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification.  *** -[NSArray initWithObjects:count:]: attempt to insert nil object at objects[0] with userInfo (null)
Assertion failed: (_Unwind_SjLj_Resume() can't return), function _Unwind_SjLj_Resume, file /SourceCache/libunwind/libunwind-24.1/src/Unwind-sjlj.c, line 326.

Here is my code for the NSFetchedResultControllers delegate methods:

-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{

    [[self eventTable] beginUpdates];

}

-(void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
    NSIndexSet* set = [NSIndexSet indexSetWithIndex:sectionIndex];
    switch (type) {
        case NSFetchedResultsChangeInsert:
            [[self eventTable] insertSections:set withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeDelete:
            [[self eventTable] deleteSections:set withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
    UITableView* tv = [self eventTable];
    switch (type) {
        case NSFetchedResultsChangeInsert:
            [tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeDelete:
            [tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeUpdate:
            [self tableView:tv configureCell:[tv cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;
    }
}

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

Any thoughts about whats causing the exception? Thanks in advance!

UPDATE 2011-02-03
Not really sure whether the error occurs when a new section is created, or an old one is deleted. I almost think that this occurs when all the rows in a section is deleted, but by some reason the controller:didChangeSection:atIndex:forChangeType is not being called.
Anyone with experience of something similar?

UPDATE 2011-02-08
I think I solved it. The problem was that some extra conditions had to be taken into concern when determining whether to delete the row/section or not.
When using the code supplied in the Apple documentation (along with a few adjustments to make it work in my view), it runs OK.

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

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

发布评论

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

评论(2

岁吢 2024-10-22 02:07:20

我想我解决了。问题是在确定是否删除行/节时必须考虑一些额外的条件。当使用 Apple 文档中提供的代码(以及一些调整以使其在我看来有效)时,它运行正常。

更新2011-03-22

基本上我使用了与SafeFetchedResultsController

I think I solved it. The problem was that some extra conditions had to be taken into concern when determining whether to delete the row/section or not. When using the code supplied in the Apple documentation (along with a few adjustments to make it work in my view), it runs OK.

UPDATE 2011-03-22

Basically I used the same approach as in SafeFetchedResultsController.

沙沙粒小 2024-10-22 02:07:20

我不知道这是否是您错误的原因,但您的委托方法中缺少 NSFetchedResultsChangeMove 案例。

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

I don't know if this is the reason for your error but you are missing the NSFetchedResultsChangeMove case in your delegate methods.

case NSFetchedResultsChangeMove:
    [changedTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    [changedTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
    break;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文