iOS - 删除UITableView中的行不会有动画效果

3

我有一个非常令人沮丧的问题。我有一个带有UITableView的应用程序。当我从表视图中删除单元格时,它会从数据模型中删除,然后我调用以下内容:

-(void)removeItem:(NSIndexPath *)indexPath {
    [self.tableView beginUpdates];

    [self.tableView deleteRowsAtIndexPaths:@[indexPath]
                      withRowAnimation:UITableViewRowAnimationRight];
    [self.tableView endUpdates];
}

我的问题是,我已经按照上面的方法尝试过了,也尝试过不使用animateWithDuration。我甚至尝试了使用CATransaction,但无论如何做,动画都不会发生。
我的模拟器开启了慢速动画,当我从列表中删除一个项目时,它会正确地移除,但没有动画效果。 它只是消失了,并留下一个空白空间,然后重新加载表格视图数据。
我在SO和Google上搜索了所有内容,但似乎找不到答案。 有什么想法吗?
也许这与我在调用上面的函数之前从数据模型中删除对象有关吗?
编辑:已删除动画块,因为它是不正确的。

尝试将其全部移出 animateWithDuration:animations: 块。表格视图会自行处理动画,您不需要做任何其他操作。 - IluTov
1
请展示你的 commitEditingStyle: 方法。 - Valentin Shamardin
谢谢大家,但是像我在问题中所说的那样,我也尝试过不使用animateWithDuration:animations:,但它并没有解决问题。@Valentin:很快会展示。 - Daniel Retief Fourie
我对代码的这部分和iOS整体都比较新。我发现我们没有实现commitEditingStyle:方法。如果有影响的话,实际从数据模型中删除是在RESTKit调用内的删除块中完成的。 - Daniel Retief Fourie
1
我建议你将动画块从问题中删除,因为它是完全错误的。否则,你分享的代码看起来是正确的。但你并没有分享太多信息。我想知道你还做了什么可能会中断动画。你说“在表视图数据重新加载之前”。我不知道你指的是什么。你没有调用reloadData吧,因为那很可能会破坏动画? - Timothy Moose
谢谢Timothy,我会编辑掉动画块。当我说表视图数据被重新加载时,意思是该单元格被移除,留下一个空白位置,紧接着其他下方的项目向上滑动以填补空缺的空间。 - Daniel Retief Fourie
4个回答

7
根据这里的内容,你根本不需要使用animateWithDuration:animations:。 只需像这样尝试即可。
-(void)removeItem:(NSIndexPath *)indexPath {
    [self.tableView beginUpdates];
    [self.tableView deleteRowsAtIndexPaths:@[indexPath]
                  withRowAnimation:UITableViewRowAnimationRight];
    [self.tableView endUpdates];
}

谢谢大家,但是像我在问题中所说的那样,我也尝试过不使用animateWithDuration:animations:,但它并没有解决问题。 - Daniel Retief Fourie

3

好的,我不知道这是不是只是不礼貌,但我感觉我将在这里回答自己的问题。

首先,感谢所有其他答案,你们当然都是正确的,但没有一个答案解决了我的问题。

事实证明,在代码中还有另一个区域执行了不同的检查,然后调用了tableView代理方法之一,似乎取消了动画。

因此,答案如下:

当您的行正在删除但动画不起作用时,请确保在动画开始之前不要调用didSelectRowAtIndexPath:indexPath。这将取消动画。


如果您没有那个问题,这是一些非常典型的扩展代码,例如示例中的两行:

请注意,facebookRowsExpanded是您必须拥有的类变量:

if ( [theCommand isEqualToString:@"fbexpander"] )
{
NSLog(@"expander button......");
[tableView deselectRowAtIndexPath:indexPath animated:NO];

NSArray *deleteIndexPaths;
NSArray *insertIndexPaths;

facebookRowsExpanded = !facebookRowsExpanded;
// you must do that BEFORE, not AFTER the animation:

if ( !facebookRowsExpanded ) // ie, it was just true, is now false
    {
    deleteIndexPaths = [NSArray arrayWithObjects:
            [NSIndexPath indexPathForRow:2 inSection:0],
            [NSIndexPath indexPathForRow:3 inSection:0],
             nil];
    [tableView beginUpdates];
    [tableView
        deleteRowsAtIndexPaths:deleteIndexPaths
        withRowAnimation: UITableViewRowAnimationMiddle];
    [tableView endUpdates];
    }
else
    {
    insertIndexPaths = [NSArray arrayWithObjects:
            [NSIndexPath indexPathForRow:2 inSection:0],
            [NSIndexPath indexPathForRow:3 inSection:0],
             nil];
    [tableView beginUpdates];
    [tableView
        insertRowsAtIndexPaths:insertIndexPaths
        withRowAnimation: UITableViewRowAnimationMiddle];
    [tableView endUpdates];
    }

// DO NOT do this at the end: [_superTableView reloadData];
return;
}

注意:您的numberOfRowsInSection方法必须使用facebookRowsExpanded。
(它大概是这样的:“如果facebookRowsExpanded返回7,则返回7,否则返回5”)
注意:您的cellForRowAtIndexPath方法必须使用facebookRowsExpanded。
(根据您是否展开,它必须返回正确的行。)

2
今天我也遇到了同样的问题,而在我的情况下,调用 reloadData 方法会取消动画效果。通过删除 reloadData 方法,动画效果重新出现了,这也是你在代码末尾评论中写的。 - user1531352

2
首先,您不需要自己动画更改。
其次,我认为您需要在开始和结束更新之间对数据源进行更改。
您的方法应该类似于这样:
-(void)removeItemAtIndexPath:(NSIndexPath *)indexPath{

    [self.tableView beginUpdates];

    // I am assuming that you're just using a plain NSMutableArray to drive the data on the table.

    // Delete the object from the datasource.
    [self.dataArray removeObjectAtIndex:indexPath.row];

    // Tell the table what has changed.
    [self.tableView deleteRowsAtIndexPaths:@[indexPath]
                  withRowAnimation:UITableViewRowAnimationRight];

    [self.tableView endUpdates];
}

我会尝试看看是否可能。从数据模型中删除是复杂的,并且发生在完全不同的地方,位于与RESTKit调用耦合的块内部。我会尝试一下,看看是否可能。我只是不知道那是否是问题所在。由于从表视图中删除的操作百分之百有效,只是没有动画效果。 - Daniel Retief Fourie

1
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];

indexPaths是一个包含NSIndexPath的数组,用于在您的表格中进行插入或删除操作。

 NSarray *indexPaths = [[NSArray alloc] initWithObjects:
    [NSIndexPath indexPathForRow:0 inSection:0],
    [NSIndexPath indexPathForRow:1 inSection:0],
    [NSIndexPath indexPathForRow:2 inSection:0],
    nil];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接