簡體   English   中英

在UITableViewController中刪除記錄會引發錯誤

[英]Deleting records in UITableViewController throws error

問題:當我單擊給定表/節行的刪除按鈕時,出現以下錯誤:“ ***由於未捕獲的異常'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上設置一個隱藏的唯一標識符,這反過來又讓我知道要過濾和刪除plist中的哪個記錄,方法是調用[array removeObjectAtIndex:uid],其中已過濾掉array plist數組。 現在唯一的問題是,NSLog中的tvc總是返回索引0處的記錄,而不是包含我單擊的刪除按鈕的行。

NSLog返回:tvc:<UITableViewCell:0x713e2c0; 框架=(0 30; 320 44); 文字=“教堂A”; autoresize = W; 層= <CALayer:0x7113e70>>-UID:-237206321-g:3-計數:3.那么為什么當tvc為索引3時,tvc返回索引0我單擊了刪除按鈕?

這僅僅是變成一團糟,還是有一個更清潔的解決方案? 但是,你還是很困惑。

此錯誤肯定與您對要加載到表中的數據的處理不當有關。 我發現處理表內容修改的最簡單,最安全的方法是根據需要進行一些調整(在tableView:commitEditingStyle:之內)

    //REMOVE A CELL FROM A SECTION 

    [yourTable beginUpdates];
    [yourTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationBottom];
    [yourTable endUpdates];
    [yourTable reloadData];

另外,您需要確保正確更新了陣列以使更改反映在表中。

這就是我最終能夠解決此問題的方式:

我改變了所有這些廢話:

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];
    }
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM