神奇的记录,从 UITableView 中删除“第 0 节中的行数无效...”

Posted

技术标签:

【中文标题】神奇的记录,从 UITableView 中删除“第 0 节中的行数无效...”【英文标题】:Magical Record, delete from UITableView "invalid number of rows in section 0..." 【发布时间】:2014-10-23 07:55:17 【问题描述】:

我正在使用Magical Record 来管理我的CoreData。 当用户删除表格中的特定单元格时,我所做的是:

设置标志并从表中删除行:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath

    [tableView beginUpdates];

    if (editingStyle == UITableViewCellEditingStyleDelete) 
        MessageTableViewCell *cell = (MessageTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];

        NSArray *sortedMessageID = [cell.photoDetails.message.message_id componentsSeparatedByString:@"_"];
        NSString *messageID = sortedMessageID[1];

        NSLog(@"cell.photoDetails.message.message_id: %@", cell.photoDetails.message.message_id);
        NSLog(@"sortedMessageID: %@", sortedMessageID);

        NSAssert(sortedMessageID[1] != nil, @"sortedMessageID[1] cannot be nil.");
        NSAssert(messageID != nil, @"messageID cannot be nil.");

        if (cell.photoDetails) 
            [MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) 
                cell.photoDetails.message.delete_message = @YES;
            ];
        

//        [self.dataSource removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

        [self performSelectorInBackground:@selector(deleteMessagesFromServer:) withObject:messageID];
    

    [tableView endUpdates];

更新服务器要删除的 ID,服务器发回 ID,如果它们匹配,我会从 CoreData 中删除它们:

@try 
        TreeNode *root = [TreeNode treeNode];
        XMLParser *parser = [[XMLParser alloc] init];
        root = [parser parseXMLFromData:data];

        if (root.key && [root.key.lowercaseString isEqualToString:@"messages"]) 
            for (TreeNode *children in root.children) 
                if ([children.key.lowercaseString isEqualToString:@"message"]) 

                    for (TreeNode *children2 in children.children) 
                        if ([children2.key isEqualToString:@"id"]) 
                            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"message.message_id ==[c] %@", children2.leafvalue];

                            BOOL isDelete =  [CoreDataPhotoRecord MR_deleteAllMatchingPredicate:predicate];
                            [[NSManagedObjectContext MR_defaultContext] MR_saveOnlySelfAndWait];
                            NSLog(@"%s, isDelete: %@", __PRETTY_FUNCTION__, @(isDelete));
                        
                    
                
            

            NSLog(@"allAcceptedRecords.count: %lu", (unsigned long)[HumanResponse allAcceptedRecords].count);
            //            NSLog(@"allAcceptedRecords.count: %lu, self.dataSource.count: %lu",
            //                  (unsigned long)[HumanResponse allAcceptedRecords].count, (unsigned long)self.dataSource.count);
        
    
    @catch (NSException *exception) 
        NSLog(@"%s, exception.reason: %@", __PRETTY_FUNCTION__, exception.reason);
    

附加代码:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    return 1;


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

//    return self.dataSource.count;
    return [HumanResponse allAcceptedRecords].count;


+ (NSArray *)allAcceptedRecords

    return [CoreDataPhotoRecord MR_findAllSortedBy:@"message.originalDate"
                                         ascending:NO
                                     withPredicate:[NSPredicate predicateWithFormat:@"message.delete_message == %@", @NO]];

编辑 - 1:

提供了日志:

2014-10-23 11:12:07.140 Human Response[426:94571] tableView.isEditing: 1
2014-10-23 11:12:07.140 Human Response[426:94571] cell.photoDetails.message.message_id: m_1000075
2014-10-23 11:12:07.141 Human Response[426:94571] sortedMessageID: (
    m,
    1000075
)
2014-10-23 11:12:07.144 Human Response[426:94756] deleteMessages: userID=3&ids=1000075&mobile=0543111797
2014-10-23 11:12:07.144 Human Response[426:94571] -[MainTableViewController tableView:numberOfRowsInSection:], count: 12
2014-10-23 11:12:07.145 Human Response[426:94571] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit/UIKit-3318.16.14/UITableView.m:1582
2014-10-23 11:12:07.146 Human Response[426:94571] CRASH:
Invalid update: invalid number of rows in section 0.  The number of rows contained in an existing section after the update (12) must be equal to the number of rows contained in that section before the update (12), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).
2014-10-23 11:12:07.158 Human Response[426:94571] Stack Trace:
(
    0   CoreFoundation                      0x277a2c37 <redacted> + 150
    1   libobjc.A.dylib                     0x34f4dc8b objc_exception_throw + 38
    2   CoreFoundation                      0x277a2af5 <redacted> + 0
    3   Foundation                          0x28472d7f <redacted> + 90
    4   UIKit                               0x2ae2c7ef <redacted> + 8150
    5   Human Response                      0x000cd823 -[MainTableViewController tableView:commitEditingStyle:forRowAtIndexPath:] + 1802
    6   UIKit                               0x2ae445e3 <redacted> + 142
    7   UIKit                               0x2af1e025 <redacted> + 68
    8   UIKit                               0x2ac92c2b <redacted> + 70
    9   UIKit                               0x2ac92bd1 <redacted> + 44
    10  UIKit                               0x2ac7d863 <redacted> + 582
    11  UIKit                               0x2ac9263d <redacted> + 588
    12  UIKit                               0x2ac5742d <redacted> + 10268
    13  UIKit                               0x2ac8c2f1 <redacted> + 784
    14  UIKit                               0x2ac8bbcd <redacted> + 524
    15  UIKit                               0x2ac623dd <redacted> + 196
    16  UIKit                               0x2aed5c29 <redacted> + 13888
    17  UIKit                               0x2ac60e39 <redacted> + 1296
    18  CoreFoundation                      0x27769377 <redacted> + 14
    19  CoreFoundation                      0x27768787 <redacted> + 218
    20  CoreFoundation                      0x27766ded <redacted> + 772
    21  CoreFoundation                      0x276b5211 CFRunLoopRunSpecific + 476
    22  CoreFoundation                      0x276b5023 CFRunLoopRunInMode + 106
    23  GraphicsServices                    0x2eaae0a9 GSEventRunModal + 136
    24  UIKit                               0x2acc11d1 UIApplicationMain + 1440
    25  Human Response                      0x000bfc41 main + 116
    26  libdyld.dylib                       0x354cdaaf <redacted> + 2
)
2014-10-23 11:12:07.161 Human Response[426:94571] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0.  The number of rows contained in an existing section after the update (12) must be equal to the number of rows contained in that section before the update (12), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
*** First throw call stack:
(0x277a2c1f 0x34f4dc8b 0x277a2af5 0x28472d7f 0x2ae2c7ef 0xcd823 0x2ae445e3 0x2af1e025 0x2ac92c2b 0x2ac92bd1 0x2ac7d863 0x2ac9263d 0x2ac5742d 0x2ac8c2f1 0x2ac8bbcd 0x2ac623dd 0x2aed5c29 0x2ac60e39 0x27769377 0x27768787 0x27766ded 0x276b5211 0x276b5023 0x2eaae0a9 0x2acc11d1 0xbfc41 0x354cdaaf)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

我做错了什么?

【问题讨论】:

我不会将该方法设为静态。但这可能不是问题的根源。似乎您的查询返回相同数量的对象。尝试输入一些打印行数的日志语句? 第一个时间表正在加载:-[MainTableViewController tableView:numberOfRowsInSection:],计数:12 我编辑了我的问题。 恐怕你需要自己调试一下。消息说明了一切。备份表视图的numberOfRowsInSection 与更新表视图时删除的行数不匹配。也许你忘了保存 ManagedObjectContext 什么的?我不确定。 【参考方案1】:

正如Sebastian Wramba 建议的那样,我改变了获取上下文的方式:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath

    [tableView beginUpdates];

    if (editingStyle == UITableViewCellEditingStyleDelete) 
        NSLog(@"tableView.isEditing: %@", @(tableView.isEditing));

        MessageTableViewCell *cell = (MessageTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];

        NSArray *sortedMessageID = [cell.photoDetails.message.message_id componentsSeparatedByString:@"_"];
        NSString *messageID = sortedMessageID[1];

        NSLog(@"cell.photoDetails.message.message_id: %@", cell.photoDetails.message.message_id);
        NSLog(@"sortedMessageID: %@", sortedMessageID);

        NSAssert(sortedMessageID[1] != nil, @"sortedMessageID[1] cannot be nil.");
        NSAssert(messageID != nil, @"messageID cannot be nil.");


        if (cell.photoDetails) 
            cell.photoDetails.message.delete_message = @YES;
            [self saveContext];

//            [MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) 
//                cell.photoDetails.message.delete_message = @YES;
//            ];
        

//        [self.dataSource removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];

        [self performSelectorInBackground:@selector(deleteMessagesFromServer:) withObject:messageID];
    

    [tableView endUpdates];


#pragma mark - Magical Records

- (void)saveContext

    [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];

【讨论】:

以上是关于神奇的记录,从 UITableView 中删除“第 0 节中的行数无效...”的主要内容,如果未能解决你的问题,请参考以下文章

神奇的记录 NSFetchedResultsController NSManagedObject 更改保存不工作

如何从 UITableView 中删除一行

从数据库中删除记录

由于自引用连接,从 UITableView 删除时应用程序崩溃

iOS开发tips-神奇的UITableView

神奇的记录删除所有孩子的一对多关系