gpt4 book ai didi

ios - 动态更改数据源导致 deleteRowsAtIndexPaths :indexes to crash

转载 作者:IT王子 更新时间:2023-10-29 08:16:13 26 4
gpt4 key购买 nike

为了让它发挥作用,我费尽了心思。我想执行 [self.tableView deleteRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationLeft];,

我如何删除的更详细的代码:

int index =  (int)[self.messages indexOfObject:self.messageToDelete];


[self.messages removeObject:self.messageToDelete];

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
NSArray *indexes = [[NSArray alloc] initWithObjects:indexPath, nil];

[self.tableView deleteRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationLeft];

这工作正常但是如果我在删除应用程序时收到推送通知(即收到新消息)将崩溃并显示如下错误:

Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit/UIKit-3347.44/UITableView.m:1327 2015-07-04 19:12:48.623 myapp[319:24083] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete row 1 from section 0 which only contains 1 rows before the update'

我怀疑这是因为我的数据源发生了变化,数组的大小发生了变化

 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

删除时的引用将不一致,因为当推送通知触发刷新时它会增加 1。有什么办法可以解决这个问题吗? deleteRowsAtIndexPaths 使用 numberOfRowsInSection 方法是否正确?

最佳答案

因此,为了解决您的问题,您需要确保您的数据源不会在某些 TableView 动画就位时发生变化。我建议执行以下操作。

首先,创建两个数组:messagesToDeletemessagesToInsert。这些将包含有关您要删除/插入哪些消息的信息。

其次,将 bool 属性 updatingTable 添加到您的 TableView 数据源。

三、添加如下函数:

-(void)updateTableIfPossible {
if (!updatingTable) {
updatingTable = [self updateTableViewWithNewUpdates];
}
}

-(BOOL)updateTableViewWithNewUpdates {
if ((messagesToDelete.count == 0)&&(messagesToInsert.count==0)) {
return false;
}
NSMutableArray *indexPathsForMessagesThatNeedDelete = [[NSMutableArray alloc] init];
NSMutableArray *indexPathsForMessagesThatNeedInsert = [[NSMutableArray alloc] init];
// for deletion you need to use original messages to ensure
// that you get correct index paths if there are multiple rows to delete
NSMutableArray *oldMessages = [self.messages copy];
for (id message in messagesToDelete) {
int index = (int)[self.oldMessages indexOfObject:message];
[self.messages removeObject:message];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
[indexPathsForMessagesThatNeedDelete addObject:indexPath];
}
for (id message in messagesToInsert) {
[self.messages insertObject:message atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[indexPathsForMessagesThatNeedInsert addObject:indexPath];
}
[messagesToDelete removeAllObjects];
[messagesToInsert removeAllObjects];

// at this point your messages array contains
// all messages which should be displayed at CURRENT time

// now do the following

[CATransaction begin];

[CATransaction setCompletionBlock:^{
updatingTable = NO;
[self updateTableIfPossible];
}];

[tableView beginUpdates];

[tableView deleteRowsAtIndexPaths:indexPathsForMessagesThatNeedDelete withRowAnimation:UITableViewRowAnimationLeft];
[tableView insertRowsAtIndexPaths:indexPathsForMessagesThatNeedInsert withRowAnimation:UITableViewRowAnimationLeft];

[tableView endUpdates];

[CATransaction commit];
return true;
}

最后,您需要在所有要添加/删除行的函数中包含以下代码。

添加消息

[self.messagesToInsert addObject:message];
[self updateTableIfPossible];

删除消息

[self.messagesToDelete addObject:message];
[self updateTableIfPossible];

此代码的作用是确保数据源的稳定性。每当有变化时,您将需要插入/删除的消息添加到数组中(messagesToDeletemessagesToDelete)。然后调用函数 updateTableIfPossible ,如果当前没有正在进行的动画,该函数将更新 TableView 的数据源(并将动画更改)。如果正在进行动画,则在此阶段什么都不做。

但是,因为我们加了补全

[CATransaction setCompletionBlock:^{
updatingTable = NO;
[self updateTableIfPossible];
}];

在动画结束时,我们的数据源将检查是否有任何新更改需要应用到 TableView ,如果有,它将更新动画。

这是一种更安全的更新数据源的方法。请告诉我它是否适合您。

关于ios - 动态更改数据源导致 deleteRowsAtIndexPaths :indexes to crash,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31144716/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com