【问题标题】:Saving NSManagedObjectContext casuing UITableView cells to disappear保存 NSManagedObjectContext 导致 UITableView 单元格消失
【发布时间】:2011-07-03 20:34:30
【问题描述】:

我遇到了以下问题。

我正在编写一个使用 CoreData 和 Apple 食谱示例作为指南的 RSS 阅读器。我有一个刷新按钮,可以重新下载 RSS 并使用 NSFetchRequest 验证是否有新数据。完成对元素的检查后,我会通过 NSManagedObjectContext 保存方法提交更改。

上下文保存后,tableView消失了!

然后我决定在 tableView 上调用 reloadData 以反映更改。所以,一旦 NSManagedObjectContext 被保存,我就会调用:

[self performSelectorOnMainThread:@selector(updateTableItems) withObject:nil waitUntilDone:NO];

-(void) updateTableItems {
    [self.tableView reloadData];
}

此操作导致单元格在滚动时删除数据,当我弹出视图并返回时,我看到所有更改并且一切正常。

我还阅读了我应该使用 NSFetchedResultsController 的线程之一,并确保 UITableView 是委托,与上一个问题相同。

我做错了什么? 为什么我看不到更改的地方? 为什么要删除单元格的内容?

谢谢!

【问题讨论】:

  • 您的表格视图显示什么数据?它是如何获取这些数据的?
  • 一个单元格呈现一个 RSS 项目。所有单元格都是带有项目标题文本的简单单元格,项目是一个 NSManagedObject,在解析时被添加到实体中......
  • 发布您的代码,以便我们为您提供帮助! @Simon 的问题是关于您的表数据源的 - 它是一组项目吗?您是否使用获取的结果控制器?发布您的 tableview 数据源方法和您的获取请求。
  • 听起来你有两个或更多线程。您使用了多少上下文?
  • 同样的事情发生在 ma 身上,我不知道为什么 - 你有没有解决这个问题?

标签: uitableview core-data ios4 nsmanagedobjectcontext


【解决方案1】:

我也遇到过类似的问题,这让我发疯了。基本上在我的代码中,有很多竞争线程试图同时更新相同的数据(表视图后面的数据),我认为这会导致 UITableView “爆炸”并且其委托方法停止触发。 (您可以通过将 NSLog 添加到委托方法中来证明这一点)。

这完全是随机发生的,很难复制。

我尝试了各种方法来解决这个问题,但唯一似乎可靠地确保它不会发生的事情是每次数据更改时完全重新创建我的 UITableView,如下所示。 (所以基本上在你调用 [self.tableView reloadData] 的地方都改变了)

// The UITableView may in rare circumstances all of a sudden failed to render 
// correctly. We're not entirely sure why this happens but its something to 
// do with multiple threads executing and updating the data behind the view 
// which somehow causes the events to stop firing.  Resetting the delegate and 
// dataSource to self isn't enough to fix things however so we have to 
// completely recreate the UITableView and replace the existing one.

UITableView* tempTableView = [[[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 387)] autorelease];
tempTableView.separatorColor = [UIColor grayColor];
tempTableView.backgroundColor = [UIColor clearColor];

if (self.tableView != nil)
{
    [tempTableView setContentOffset:self.tableView.contentOffset animated:NO];
}

tempTableView.delegate = self;
tempTableView.dataSource = self;
[tempTableView reloadData];  

 if (self.tableView != nil) {
     [self.tableView removeFromSuperview];
     self.tableView = nil;
 }

 [self.view addSubview:tempTableView];
 self.tableView = tempTableView;

我知道这不是理想的修复方法,也没有真正解释问题,但我认为这是一个 iOS 错误。不过,欢迎任何其他意见。

【讨论】:

    【解决方案2】:

    听起来您在不同的线程上使用了两个或更多上下文。您在后台线程上下文中提交保存,但不要将更改与连接到前端线程上的 UI 的上下文合并。这会导致 UI 上下文与商店不同步,从而导致滚动时表格行消失。

    当您通过离开视图弹出控制器时,上下文将被释放,这样当您第二次返回视图时,您将获得一个新的上下文,以了解对存储的更改。

    为防止出现此问题,请在保存后台上下文后立即对前台上下文调用 refreshObject:mergeChanges:。让前台上下文从后台上下文注册 NSManagedObjectContextDidSaveNotification

    【讨论】:

    • 我实际上只运行一个线程。考虑一个 RSS 刷新按钮,单击时我会显示“请稍候”AlertView,在后台我再次下载 RSS,解析它.. 验证是否有任何更改,如果有,我添加它们。完成后,我保存上下文!这与我在我的观点之间传递的背景相同。我读了一篇关于带线程的核心数据的好文章,每个线程都应该有自己的上下文,然后将它们合并..但这不是这里的情况。当我点击保存时,繁荣单元格的内容正在消失..
    • 如果您不使用线程,为什么还要打扰performSelectorOnMainThread:?您不是从 tableview 控制器调用reloadData 吗?在这一点上,如果这不是线程问题,我真的没有足够的信息来解决任何问题。表行清空的唯一原因是 numberOfRowsInSection 返回 0 以使表认为它没有可显示的内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    相关资源
    最近更新 更多