【问题标题】:Deleting records in UITableViewController throws error删除 UITableViewController 中的记录会引发错误
【发布时间】:2011-08-26 21:58:08
【问题描述】:

问题:当我单击给定表/节行的删除按钮时,我收到以下错误:“*** 由于未捕获的异常 'NSInternalInconsistencyException' 而终止应用程序,原因:'无效更新:无效的行数第 0 节。更新后现有节中包含的行数 (4) 必须等于更新前该节中包含的行数 (4),加上或减去从该节中插入或删除的行数(插入 0 个,删除 1 个)。'"

从我读过的有关此症状的其他帖子中,我推测我想手动删除我的数据源数组中的一个元素,但不确定如何在此方法中访问该部分的数组:

// COMMIT EDITING STYLE
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"indexPath: %@", indexPath);    

if (editingStyle == UITableViewCellEditingStyleDelete) {
    // Delete the row from the data source        
   [tableView beginUpdates];
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    [tableView endUpdates]; // throws error here
    [tableView reloadData];   
}   
else if (editingStyle == UITableViewCellEditingStyleInsert) {
    // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}   

}

我认为这种情况的复杂性是由于我从中提取数据的 plist (FormEntries.plist) 在我的应用程序中保存了各种事物的用户输入,因此我不得不调用和过滤它适用于每个部分。这可以很好地填充 UITableView 及其所有部分,但是因为正在为每个部分创建一个新的过滤数组,所以我不确定如何再次访问它以删除元素,从而纠正上述问题错误信息。以下是我为每个表格部分加载数据的方式:

// CELL FOR ROW AT INDEXPATH
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath (NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";    
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}

NSNumber *numScreenId = [[arrayOfModulesScreens objectAtIndex: indexPath.section] objectForKey: @"id"];
NSMutableArray *arrayRecords = [epFrameWork selectPlist: @"FormEntries" filterByKey: @"screen_id" keyValue:numScreenId];

NSString *strTitle = [[arrayRecords objectAtIndex: indexPath.row] objectForKey: @"storage_string"];

cell.textLabel.text = strTitle;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;           
return cell;

}

-- 不确定这是否有助于诊断问题,但仍然如此 ---

// TITLE FOR HEADER IN SECTION
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [[arrayOfModulesScreens objectAtIndex: section] objectForKey: @"screen_title"];
}

// NUMBER OF SECTIONS IN TABLE VIEW 
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [arrayOfModulesScreens count];
}


// NUMBER OF ROWS IN SECTION
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSNumber *numScreenId = [[arrayOfModulesScreens objectAtIndex: section] objectForKey: @"id"];
NSMutableArray *arrayRecords = [epFrameWork selectPlist: @"FormEntries" filterByKey: @"screen_id" keyValue:numScreenId];
int rowCount = [arrayRecords count];
return rowCount;    
}

处理这种情况或解决上述错误消息的最佳方法是什么?

-- 更新--

所以这就是我试图确定要删除的 plist 记录的方法,假设这是我需要做的以解决原始错误:

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

int g = indexPath.row;
int count = -1;
UITableViewCell *tvc = [[UITableViewCell alloc] init];
for(id element in tableView.subviews) {
    if([element isKindOfClass:[UITableViewCell class]]) {
       count +=1; 
        NSLog(@"g: %d - count: %d", g , count);
        if(count == g) {
            tvc = element;
            NSLog(@"tvc: %@ - UID: %@ - g: %d - count: %d", tvc, tvc.detailTextLabel.text, g , count);
        }
    }
}

我的逻辑是在 cellForRowAtIndexPath 方法中的 tvc.detailTextLabel.text 上设置一个隐藏的唯一标识符,这反过来会让我知道通过调用 [array removeObjectAtIndex:uid] where array 来过滤和删除 plist 中的哪条记录是我过滤的 plist 数组。现在唯一的问题是 NSLog 中的 tvc 总是返回索引 0 处的记录,而不是包含我单击的删除按钮的行。

NSLog 返回:tvc: > - UID: -237206321 - g: 3 - count: 3. 那么为什么 tvc 在索引 3 时返回索引 0 我点击了删除按钮?

这只是变得一团糟还是有更清洁的解决方案?但是你,还是被难住了。

【问题讨论】:

    标签: iphone objective-c uitableview


    【解决方案1】:

    此错误与您对尝试加载到表中的数据处理不当有关。我发现处理修改表格内容的最简单和最安全的方法是按照这些思路做一些事情,并进行必要的调整(在 tableView:commitEditingStyle 内:)

        //REMOVE A CELL FROM A SECTION 
    
        [yourTable beginUpdates];
        [yourTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationBottom];
        [yourTable endUpdates];
        [yourTable reloadData];
    

    此外,您需要确保您的数组已正确更新,以使更改反映在表格中。

    【讨论】:

    • 刚刚进行了推荐的更新。抛出相同的错误,但在这一行 [tableView endUpdates];。我已更新我的原始帖子以反映此更新。
    • NSLog(@"indexPath: %@", indexPath);作为 commitEditingStyle 方法中的第一条语句产生: indexPath: 2 个索引 [0, 3]。甚至不确定这意味着什么。 3 告诉我们删除了 1 行,因为 1 比错误中提到的 4 少?表格行和表示该行的数组元素有什么区别?我想他们是两个不同的东西。抱歉,我对这一切还是很陌生。
    • 只需阅读 NSIndexPath 类参考,现在这部分就更有意义了。现在我只需要弄清楚如何解决原来的错误。
    • 是的。我已经构建了一个相当笨重的工作,但仍在尝试解决为什么那个不工作。是否有一个简单的解决方案,或者我应该将我的工作作为另一个答案发布?或者我应该在 cmets 部分发布我的解决方法代码?
    • 我刚刚发布了我的解决方法代码作为对原始代码的更新。
    【解决方案2】:

    这就是我最终能够解决问题的方法:

    我改变了所有这些废话:

    int g = indexPath.row;
    int count = -1;
    UITableViewCell *tvc = [[UITableViewCell alloc] init];
    for(id element in tableView.subviews) {
    if([element isKindOfClass:[UITableViewCell class]]) {
       count +=1; 
        NSLog(@"g: %d - count: %d", g , count);
        if(count == g) {
            tvc = element;
            NSLog(@"tvc: %@ - UID: %@ - g: %d - count: %d", tvc, tvc.detailTextLabel.text, g , count);
        }
      }
    }
    

    到一个简单的行:

    UITableViewCell *cell = [[self tableView] cellForRowAtIndexPath:indexPath];   
    

    这使我能够识别我正在使用的单元格。所以我最终的工作代码如下所示:

    // COMMIT EDITING STYLE
    // Override to support editing the table view.
    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
    {
    
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        UITableViewCell *cell = [[self tableView] cellForRowAtIndexPath:indexPath];        
        [epFrameWork deleteRecordFromPlist:@"FormEntries" uid:cell.detailTextLabel.text];        
        [tableView reloadData];         
    
    }   
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
     }   
    }
    
    -(void) deleteRecordFromPlist:(NSString *)plist uid:(NSString *)uId {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *tmpFileName = [[NSString alloc] initWithFormat:@"%@.plist", plist];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:tmpFileName];
    NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:path];
    NSDictionary *dict = [[NSDictionary alloc] init];
    NSString *tmpUid;
    for(int i=0; i < [array count]; i++) {
        dict = [array objectAtIndex:i];
        tmpUid = [dict valueForKey:@"uid"];
        if([tmpUid isEqualToString:uId]) {
           [array removeObjectAtIndex:i];
           [array writeToFile:path atomically:YES];
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-22
      • 1970-01-01
      相关资源
      最近更新 更多