-[UITableView _endCellAnimationsWithContext:]中的断言失败


89

希望这将是一个快速修复。我一直在试图找出我不断得到的错误。该错误在下面列出,而附录则在下面。

任何帮助表示赞赏。

谢谢

2012-04-12 21:11:52.669 Chanda [75100:f803] ---中的断言失败-[UITableView _endCellAnimationsWithContext:]/SourceCache/UIKit_Sim/UIKit-1914.84/UITableView.m:1037 2012-04-12 21:11:52.671 Chanda [75100:f803] ---因未捕获的异常而终止应用程序NSInternalInconsistencyException' ,原因:“无效的更新:第0节中的行数无效。更新(2)之后,现有节中包含的行数必须等于更新(2)之前该节中包含的行数,再加上或减去从该部分插入或删除的行数(插入1,删除0),再加上或减去移入或移出该部分的行数(移入0,移出0)。

#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize databaseName,databasePath; 

- (BOOL)application: (UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions {
    self.databaseName = @"Customers.db";

    NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentDir = [documentPaths objectAtIndex:0];
    self.databasePath = [documentDir stringByAppendingPathComponent:self.databaseName];
    [self createAndCheckDatabase];

    return YES;
}

- (void)createAndCheckDatabase {
    BOOL success;

    NSFileManager *fileManager = [NSFileManager defaultManager];
    success = [fileManager fileExistsAtPath:databasePath];

    if (success) return; 

    NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:self.databaseName];

    [fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
}

@end

3
您应该将该代码移至类,并可能在后台线程中执行它。无论如何,当您尝试删除行而不实际减少表视图数据源提供的行数时,通常会出现此错误。您实际上是在删除行时删除数据吗?如果您不删除任何行,可以提供表视图数据源实现吗?
君士坦丁·萨鲁哈斯

Answers:


43

我看不出您向我们展示这部分代码的原因。我假设您的错误必须与代码中的此部分相关

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

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

您可能在这些数据源方法之一中犯了一个错误。目前尚无法确定到底是什么错误,但我认为可能是这样的:例如,您要告诉表视图中numberOfRowsInSection您要保留和设置n行,然后在其中cellForRowAtIndexPath仅处理n-1行。

抱歉,此答案无法达到应有的精确度。如果您向我们展示您对数据源的实现,则更容易知道发生了什么。


26

就像孙子所说的那样最好不战而胜。就我而言,每当我看到这种错误消息(即删除的行之间的差异已删除等)..我什至都不调试任何东西..我只是避免在重新加载行等处进行额外的调用..这是99%发生此错误的情况。

这是发生此错误的常见情况:我有一个UINavigationController,它有一个UITableView,当我单击一行时,它会推一个新的UITableView,依此类推。当我弹出最后一个UITableview并返回到它UITableView之前时,总是会发生此错误,这时我对该loadIt函数进行了不必要的调用,该函数基本上插入了行并重新引用了UITableView

发生这种情况的原因是因为我错误地将loadIt函数放置在viewDidAppear:animated而不是中viewDidLoadviewDidAppear:animated每次UITableView显示时viewDidLoad都会调用,只会调用一次。


3
谢谢,说得好。您的第一段使我走上了解决类似问题的正确道路。
scrrr

2
这是我的荣幸@scrrr :)
2013年

这改变了我看待它的方式-通过使其不相关而解决了问题。你摇滚!
查理

向viewDidAppear而不是viewDidLoad致敬。那正是我的问题,我已经处理了好几个星期。
GrandSteph 2015年

1
我打印了您的《孙子兵法》报价单并将其粘贴在屏幕顶部。感谢您的报价,并帮助我找到大量的冗余代码:)
Adrian

24

删除行时,请记住,它还在更新时检查以下部分:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)theTableView

如果要删除部分中最后一项的行,则需要删除整个部分(否则可能会导致部分计数错误并抛出此异常)。


1
这是纯金!钉在头上!正是我的问题。
phatmann

6

不要忘记更新确定numberOfRowsInSection的数组。在制作动画和删除之前,需要对其进行更新

我们检查节中的行数是否为1,因为我们必须删除整个节。

如果有人可以使这个答案更清楚,请纠正我。

[self.tableView beginUpdates];
if ([tableView numberOfRowsInSection:indexPath.section] == 1) {

   [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
} else {

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

4

我将每个小节元素放在单独的数组中。然后将它们放入另一个array(arrayWithArray)。我在这里针对此问题的解决方案:

[quarantineMessages removeObject : message];
[_tableView beginUpdates];
if([[arrayWithArray objectAtIndex: indPath.section] count]  > 1)
{
    [_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indPath] withRowAnimation:UITableViewRowAnimationBottom];
}
else
{
    [_tableView deleteSections:[NSIndexSet indexSetWithIndex:indPath.section]
              withRowAnimation:UITableViewRowAnimationFade];
}
[_tableView endUpdates];

1
对我来说,解决它的是开始和结束更新,谢谢!
Mark W

2
我不知道该部分是否变空以及是否需要对其进行动画处理……该死!谢谢!
2014年

1
得到了我的代码,可以从此答案中获得很多帮助。在下面发布。
love2script12

2

我有同样的错误。

我正在使用以下几行

UINib *myCustomCellNib = [UINib nibWithNibName:@"CustomNib" bundle:nil];
[tableView registerNib:myCustomCellNib forCellReuseIdentifier:@"CustomNib"];

在我的viewDidLoad方法中注册笔尖,因为我有另一个也与同一类相关联的笔尖。因此,线

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"GBFBLoadingCell"];

除非我在viewDidLoad中注册了笔尖,否则返回nil。

我的问题是我忘记在属性检查器中为文件“ CustomNib.xib”和“ CustomNib〜iphone.xib”设置标识符。(或更准确地说,在XCode的属性检查器中键入标识符后,我忘了按Enter键,因此新名称无法保存。)

希望这可以帮助。


2
我认为您的答案与问题无关。
DawnSong 2015年

2

如果您正在使用NSFetchedResultsController像我这样的用户并在后台线程中更新数据,请不要忘记在委托中开始和结束更新:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView beginUpdates];
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];
}

2

我遇到了同样的错误,尝试时可以[tableView reloadData]正常工作。错误实际上在行中

[TabView insertRowsAtIndexPaths:indexPathsArray withRowAnimation:UITableViewRowAnimationRight];

当我尝试检查indexPath值时,它们不符合要求。

我通过更改中的值来修复它indexPathsArray

希望这可以帮助 。


1

它可能是UITableViewDataSource协议方法之一

对于

- tableView:numberOfRowsInSection:

它应返回等于或的总和或结果的整数

-insertRowsAtIndexPaths:withRowAnimation:和/或-deleteRowsAtIndexPaths:withRowAnimation

对于

- numberOfSectionsInTableView:

它应返回等于或的总和或结果的整数

-insertRowsAtIndexPaths:withRowAnimation: 和/或 -deleteSections:withRowAnimation:


0

我在核心数据库中遇到了同样的问题。如果您使用许多FRC,则只需在numberOfSectionsInTableView中的每个条件内重新加载tableview。


2
核心资料也有这个问题。您能详细说明一下您的食谱吗?
Drux

0

我只是在使用Swift和FRC支持的数据存储来管理信息时发生了这种情况。在删除操作中添加一个简单的检查以评估当前indexPath.section可以避免不必要的调用。我想我理解为什么会发生此问题...基本上,只要我的数据集为空,我都会在第一行中加载一条消息。由于存在虚假行,因此产生了一个问题。

我的解决方案

... delete my entity, save the datastore and call reloadData on tableView
//next I add this simple check to avoid calling deleteRows when the system (wrongly) determines that there is no section.

       if indexPath.section > 0 {

        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .None)

            }

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.