【问题标题】:Dynamically updating sections of UITableView without using reloadData在不使用 reloadData 的情况下动态更新 UITableView 的部分
【发布时间】:2012-09-09 06:02:42
【问题描述】:

首先,如果此问题已得到答复,我深表歉意。我已经和这个斗争了太久了。我将不胜感激。

我正在开发一个应用程序,该应用程序从不同的 Web 源异步获取数据并将其解析为由我的主模型处理的对象。该模型为 UITableView 提供信息。接收和解析数据后,我需要修改表格视图中的部分和行数。我首先接收决定节数的数据,然后异步接收修改每个节中的行数及其内容的数据。我已经设置了表格视图数据源。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.

    return [self.sijainti.pysakit count];

}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    //if ([[[self.sijainti.pysakit objectAtIndex:section] ajatStr] count] == 0) return 1;
    NSLog(@"ajatStr of section: %d  count: %d",section, [[[self.sijainti.pysakit objectAtIndex:section] ajatStr] count]);
    return [[[self.sijainti.pysakit objectAtIndex:section] ajatStr] count];
}

对象名称是芬兰语(长话短说)。 numberOfRowsInSection 的第二行被注释以简化调试。现在,因为数据是动态的,所以当我准备好显示数据时,我需要更新界面,否则用户在滚动离开并再次返回之前不会知道它。我有一个方法:

- (void)updateRowWithCell:(SCPysakki *)valmisPysakki {
    if (!valmisPysakki.isInArray) return;

    int section = [self.sijainti.pysakit indexOfObject:valmisPysakki];

    [self.tableView beginUpdates];
    NSIndexSet *sectionSet = [NSIndexSet indexSetWithIndex:section];
    [self.tableView reloadSections:sectionSet withRowAnimation:UITableViewRowAnimationFade];
    [self.tableView endUpdates];
}

只有在知道节数后才会调用它。由于效率和动画,我不想使用 reloadData。我曾经进行过这样的设置,因此我只有行,并且只是在行内绘制行。但是一旦行变得比iphone屏幕高,就变得很不清楚,因为你看不到标题。所以我把它们做成了部分,这些行绘制了真正的行。然后我突然面临一个问题。 reloadRowsAtIndexPaths: withRowAnimation: 工作得很好,但是使用 reloadSections: withRowAnimation: 给了我这个异常:

* -[UITableView _endCellAnimationsWithContext:] 中的断言失败,/SourceCache/UIKit_Sim/UIKit-1914.84/UITableView.m:1037

2012-09-17 04:11:27.769 pysappi[2351:f803] * 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无效更新:第 1 节中的行数无效. 更新后现有节中包含的行数 (1) 必须等于更新前该节中包含的行数 (0),加上或减去从该节中插入或删除的行数 (0已插入,0 已删除)并加上或减去移入或移出该部分的行数(0 移入,0 移出)。'

我可以通过将 [self.tableView endUpdate] 和 [self.tableView endUpdate] 添加到更新方法来消除此问题。但是哦,不,只有当我:

  1. 在接收到决定节数的数据后使用 reloadData(这反过来又缩短了 tableview 以便在每次更新后整个更新后用户在表顶部。我宁愿动态更新节,不使用 reloadData,除非删除部分,但如果我尝试这样做,我会再次遇到异常。)

  2. 仅在接收到一行的数据后更新这些部分(因此,如果我在收到所有数据后尝试更新该部分中的所有行,我会再次遇到异常。)

现在这造成了创建良好用户界面变得不可能的情况。我确信根本问题并没有通过 start 和 end 更新调用来解决,但这只是出于一些非常奇怪的原因解决了它。

我还尝试使用 insertRowsAtIndexPaths: 手动添加行并手动更新它们,但这会返回完全相同的错误。在长时间的调试过程中,我已经能够确定此异常在 cellForRowAtIndexPath: 被调用后出现,并且它为更新期间添加的新行之一返回一个单元格,即使 numberOfRowsInSection 应该已经更新了行数。我还认为,如果这几种情况适用,这就是开始和结束更新方法使行更新起作用的原因。

除了我上面解释的内容之外,唯一有效的是仅使用 reloadData,但考虑到更新量,这实际上是不可能的。

这比我想象的要长得多,现在是凌晨 4.30。由于这个例外,我不是第一次起这么晚了。如果您需要更多信息,请询问。提前谢谢你。

【问题讨论】:

  • 我只是在这里推测-但是如果您要更改部分的数量-您可能会遇到此代码的问题。 numberOfSections 将被缓存 - 您需要重新加载表以添加新部分,然后调用 reloadSections。无论您尝试重新加载多少个部分,tableview 都不知道,因此会出现内部一致性错误。我可能是错的,但是看到在 numberOfSections 上放置了一个断点 - 看看当你添加新部分时是否再次调用它 - 它可能不是。
  • @stackmonster 我想我的异常在错误的地方被切断了。问题不在于添加部分。它在更新行。
  • 在那里编辑了整个异常,看看。在 uitable 视图请求之后引发异常,并且 cellForRowAtIndexPath 返回一个具有更新之前不存在的索引路径的单元格。我已经 NSLogged numberofrowsinsection 并在更新期间调用它,所以我不知道为什么它不接受新行。是因为 numberOfRowsInSection 返回缓存的答案而不是指定的答案吗?
  • 更新后现有部分中包含的行数 (1) 必须等于更新前该部分中包含的行数 (0), - 您有一个包含零行的部分,并且对一行进行了更新 - 可可没有将其视为插入并让您失败

标签: objective-c ios uitableview


【解决方案1】:

(在 cmets 中回答。转换为社区 wiki 答案。见 Question with no answers, but issue solved in the comments (or extended in chat)

@deleted_user 写道:

更新后现有节中包含的行数 (1) 必须等于更新前该节中包含的行数 (0), - 您有一个包含零行的节并使用行 - 可可没有将其视为插入并让您失望

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-21
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 2016-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多