UITableView 具有多个 NSFetchedResultsController 导致断言失败

发布于 2024-10-11 18:35:53 字数 1596 浏览 3 评论 0原文

我有一个包含 3 个部分的 UITableView,每个部分都通过唯一的 NSFetchedResultsController 提供。

在插入、更新表时,我从 NSFetchedResultsController -controllerDidChangeContent 收到断言失败

我的猜测是下面方法中的 indexPaths 存在问题,因为每个控制器只有单个部分 (0),并且对于第 0 部分中的控制器,不会发生故障。

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

所以我的问题是,如何确定正在处理哪个控制器(来自哪个部分)并相应地修改 indexPath 以及这是否是正确的方法?可能还有使用多个 nsfetchedresultscontrollers 和一个 uitableview 的任何示例。

I have a UITableView with 3 sections and each section is being fed through unique NSFetchedResultsController.

I am getting Assertion failure from the NSFetchedResultsController -controllerDidChangeContent, when inserting, updating...the table.

My guess is issue with indexPaths coming in method below as every controller has only single section (0) and for controller in section 0 the failure doesn't happen.

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

So my question is, how can I determine which controller (from which section) is being processed and modify the indexPath accordingly and if that's the right way of doing it? And possibly any examples of using several nsfetchedresultscontrollers with one uitableview.

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

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

发布评论

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

评论(2

爱*していゐ 2024-10-18 18:35:53

所以我的猜测实际上是正确的:

当每个控制器输入以下函数

  • (void)controller:(NSFetchedResultsController*)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath*)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath*)

newIndexPath除了为第 0 部分设置的控制器之外,indexPath 对于每个控制器都是不正确的。

每个控制器只有一个部分 - 在我的例子中为 0,但更重要的是,这些部分与表部分不对应。

因此,我当前实现的解决方法(不是很好,因此可能会返工)是检查控制器的cacheName,并基于此修改indexPath/newIndexPath的部分,

如下所示:

if([[controller cacheName] isEqualToString:@"sectionX"])
{
  indexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:<add correct section>];
  newIndexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:<add correct section>];
}

So my guess was actually correct:

as each controller enters following function

  • (void)controller:(NSFetchedResultsController*)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath*)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath*)newIndexPath

the indexPath is incorrect for every controller apart from the one that is setup for section 0.

Each controller has only single section - 0 in my case but more importantly, these sections do not correspond to the table sections.

So the workaround I currently implemented (not great, so will probably rework) is to check for cacheName of the controller and based on that modify the section for indexPath/newIndexPath

something like this:

if([[controller cacheName] isEqualToString:@"sectionX"])
{
  indexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:<add correct section>];
  newIndexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:<add correct section>];
}
独守阴晴ぅ圆缺 2024-10-18 18:35:53

我不确定它是 FetchedResultController。

插入和删除行调用将在某个时刻要求 tableView 重新加载,然后它将向委托和数据源方法询问 numberOfRowsInSection、cellForRowAtIndexPath 等。

可能发生的情况是模型和 tableView 不同步,并导致控制器发出警告。

    [tableView beginUpdates];

     if (editingStyle == UITableViewCellEditingStyleDelete) {

        NSMutableDictionary *item = [self.itemList objectAtIndex:indexPath.row];
    // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [self.itemList removeObjectAtIndex:indexPath.row];      

}   
    [tableView endUpdates];

尝试这样的方法,其中对 tableView 和底层模型的所有更改都包含在
开始更新和结束更新。这些将导致 tableView 等待单元格的绘制,直到您给出“确定”。

如果不是上述情况,这里是我通常处理 tableView 中多个部分的方式。

在标头中,为各节声明一个 typedef 枚举;

typedef enum {

    SectionTypeName,
    SectionTypeAge,
    SectionTypeSkills,

} SectionType;

//in the implementation

switch (indexPath.section) {
    case SectionTypeName:
        //do thing in the name section
        break;
    case SectionTypeAge:
        //do thing in the name section
        break;
    case SectionTypeSkills:
        //do thing in the name section
        break;          
    default:
        break;
}

我几乎在每个 tableView 委托/数据源方法中都有 switch() 。
这使得很容易弄清楚哪个部分正在被处理以及它的作用。

I am not sure it is the FetchedResultController.

The insert and delete row call will at some point ask the tableView to reload, it will then ask the delegate and datasource methods for numberOfRowsInSection, cellForRowAtIndexPath etc.

What probably happens is that the model and the tableView are out of sync and it causes the controller to throw a warning.

    [tableView beginUpdates];

     if (editingStyle == UITableViewCellEditingStyleDelete) {

        NSMutableDictionary *item = [self.itemList objectAtIndex:indexPath.row];
    // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [self.itemList removeObjectAtIndex:indexPath.row];      

}   
    [tableView endUpdates];

Try something like this, where all changes to the tableView and the underlying model are wrapped in
the beginUpdates and endUpdates. Those will cause the tableView to wait with the drawing of the cell until you give the 'OK'.

If the above is not the case here is how I usually deal with multiple sections in a tableView.

In your header you declare a typedef enum for the sections;

typedef enum {

    SectionTypeName,
    SectionTypeAge,
    SectionTypeSkills,

} SectionType;

//in the implementation

switch (indexPath.section) {
    case SectionTypeName:
        //do thing in the name section
        break;
    case SectionTypeAge:
        //do thing in the name section
        break;
    case SectionTypeSkills:
        //do thing in the name section
        break;          
    default:
        break;
}

I have the switch() in almost every tableView delegate/datasource method.
This makes it very easy to figure out which section is being processed and what it does.

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