关于UITableView和deleteRowsAtIndexPaths的问题

时间:2011-09-24 01:59:27

标签: iphone objective-c uitableview

关于stackoverflow的第一个问题(<<< n00b)。我正在处理涉及UITableViews和plists的第一个项目,我遇到了问题。

属性列表包含一个包含3个部分/类别(每个数组)的字典,以及每个部分/类别中的条目数。

列表加载得很好。在我尝试从列表中删除单个条目之前,问题才会发生。

这是我的代码:

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

if (editingStyle == UITableViewCellEditingStyleDelete) {

    //make array of the objects and remove the selected object from that array.
    NSMutableArray *delArray = [faves objectForKey:[entries objectAtIndex:indexPath.section]];
    [delArray removeObjectAtIndex:indexPath.row];

    //set entries to the value of the array, now sans the removed object.
    self.entries = delArray;
    [delArray release];

    //write the updated entries to the plist file.
    NSArray *rootPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docsPath = [rootPath objectAtIndex:0];
    NSString *plistFile = [docsPath stringByAppendingPathComponent:@"Data.plist"];
    [faves writeToFile:plistFile atomically:YES];

    //update the actual tableview. This is where things go awry.
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES]; //ends up trying to load the sections instead of the entries = wrong number of list items returned = crash!

    //[tableView reloadData]; //works if I only use this line, but the list updates wrong, showing each entry as a section header.
    }
}

正确地从plist中删除了条目,但该表无法正确更新并导致应用程序崩溃。我在下面列出了错误代码。

2011-09-23 18:40:19.732 MyApp[10314:b303] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1448.89/UITableView.m:974
2011-09-23 18:40:19.734 MyApp[10314:b303] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections.  The number of sections contained in the table view after the update (5) must be equal to the number of sections contained in the table view before the update (3), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).'

第一个数字(5)与受影响类别中应保留多少记录一致,但第二个数字(3)表示类别数量。就像我上面说的那样,条目从plist中删除 - 只是不是表格。

2 个答案:

答案 0 :(得分:2)

考虑以下两种方法:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [entries count];
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
   NSString *key = [entries objectAtIndex:section];
   NSArray *sectionNames = [faves objectForKey:key];
   return [sectionNames count];
} 

“entries”似乎是一个关键名称(NSString)的NSArray,而“faves”是一个部分内容的NSDictionary(NSArrays)。

问题是你要用一个部分的内容数组替换你的键名(self.entries)数组。我扩展了你的代码,使逻辑错误更加明显:

// query for section key name by section index
NSString       * keyName        = [entries objectAtIndex:indexPath.section];

// retrieve array of a section's datasource (array of rows)
NSMutableArray * delArray = [faves objectForKey:keyName];

// remove row from a section's datasource
[delArray removeObjectAtIndex:indexPath.row];

// ERROR: assign an array of rows to array used for section names
self.entries = delArray;

将代码更改为以下内容应删除UITableView生成的断言:

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

if (editingStyle == UITableViewCellEditingStyleDelete) {

//make array of the objects and remove the selected object from that array.
NSMutableArray *delArray = [faves objectForKey:[entries objectAtIndex:indexPath.section]];
[delArray removeObjectAtIndex:indexPath.row];

//write the updated entries to the plist file.
NSArray *rootPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [rootPath objectAtIndex:0];
NSString *plistFile = [docsPath stringByAppendingPathComponent:@"Data.plist"];
[faves writeToFile:plistFile atomically:YES];

//update the actual tableview. This is where things go awry.
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES]; //ends up trying to load the sections instead of the entries = wrong number of list items returned = crash!

//[tableView reloadData]; //works if I only use this line, but the list updates wrong, showing each entry as a section header.
}

答案 1 :(得分:0)

如果从plist文件中获取数组时tableview删除。文档目录是最佳选择。(请参阅下文)删除行并再次更新plist文件。在UITableViewCellEditingStyleDelete中。

标题

中的

    @property (nonatomic, retain) NSMutableArray *arForTable;

在CellForRowAtindexpath

  cell.textLabel.text=[[ self.arForTable  objectAtIndex:indexPath.row]    
  valueForKey:@"key"];

  - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
  {

return 1;
   }

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

return [self.arForTable count];
    }

in

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


   if (editingStyle == UITableViewCellEditingStyleDelete) {

    NSError *error;

    NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];

    NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"data.plist"];
    NSFileManager *fileManager = [NSFileManager defaultManager];

    if (![fileManager fileExistsAtPath:dataPath]) 
 {
    NSString *bundle = [[NSBundle mainBundle] pathForResource:@"data" ofType:@"plist"];

    [fileManager copyItemAtPath:bundle toPath:dataPath error:&error]; 
}

[self.arForTable removeObjectAtIndex:indexPath.row];
[self.arForTable   writeToFile:dataPath atomically:YES];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
   }
 }