从 uitableview 中删除 + 写入 plist 不起作用

Posted

技术标签:

【中文标题】从 uitableview 中删除 + 写入 plist 不起作用【英文标题】:Delete from uitableview + write to plist not working 【发布时间】:2013-11-17 10:29:06 【问题描述】:

我想从 uitableview 中删除并将其写入我的 plist。我对这个 Objective-c ios 编码很陌生,所以请原谅我的错误

现在我的代码崩溃了:

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 (11) must be equal to the number of rows contained in that section before the update (11), 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).'

这是我在 mainViewcontroller 中的代码

- (void)viewWillAppear:(BOOL)animated
// Property List.plist code
//Gets paths from root direcory.
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
//Get documents path.
NSString *documentsPath = [paths objectAtIndex:0];

//Get the path to our PList file.
plistPath = [documentsPath stringByAppendingPathComponent:@"Servers.plist"];

//Check to see if Property List.plist exists in documents.
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath])
    [[NSFileManager defaultManager]copyItemAtPath:[[NSBundle mainBundle]pathForResource:@"Servers" ofType:@"plist"] toPath:plistPath error:nil];
    //If not in documents, get property list from main bundle.

arrayA = [[NSMutableArray alloc] initWithContentsOfFile:plistPath];
NSLog(@"%@\n%@", arrayA, [arrayA valueForKey:@"Hostname"]);

tableData = [arrayA valueForKey:@"Hostname"];
[super viewWillAppear:animated];
[self.tableView reloadData];



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


    return [tableData count];


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


static NSString *cellIdentifier = @"showServerAction";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

if (cell == nil) 

    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];



cell.textLabel.text = [tableData objectAtIndex:indexPath.row];

return cell;


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

if (editingStyle == UITableViewCellEditingStyleDelete) 
    [tableView beginUpdates];

    [arrayA writeToFile:plistPath atomically: TRUE];
    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    [tableView endUpdates];


更新 这是我的 plist 的外观。这是一个 NSMutableArray

【问题讨论】:

【参考方案1】:

试试这个:

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

  if (editingStyle == UITableViewCellEditingStyleDelete) 

    [tableView beginUpdates];

    // You are going to modify the table view, but you also need
    // to modify the data source of your table. Since tableData
    // is derived from the content of arrayA, the actual data
    // source is arrayA, so we start with that (also, arrayA is
    // a mutable array, so we are allowed to remove objects from
    // it).
    [arrayA removeObjectAtIndex:indexPath.row];

    // Now we also need to modify tableData. If you don't do this,
    // tableData will report the wrong number of rows when
    // numberOfRowsInSection() is called the next time. This is the
    // direct source of the error that you mention in your question
    // (carefully read the error message, it's really meaningful!).
    // A small problem is that tableData is not a mutable array,
    // so we cannot use removeObjectAtIndex: to modify it (that's
    // probably the source of the error you got with Ilya's answer).
    // The solution is to simply recreate tableData from scratch
    // from the content of arrayA.
    tableData = [arrayA valueForKey:@"Hostname"];

    [arrayA writeToFile:plistPath atomically: TRUE];
    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

    [tableView endUpdates];
  

【讨论】:

esxuce 我,但我该怎么做? @KennyVB 我已经编辑了我的答案,希望这会有所帮助(我最初的答案只对了一半)。【参考方案2】:

删除后必须更改tableData,然后像这样重新加载表视图:

[self.tableView reloadSections:[NSIndexSet  indexSetWithIndex:<#(NSUInteger)#>] withRowAnimation:<#(UITableViewRowAnimation)#>];//With animation

或者重新加载所有没有动画的表格:

[self.tableView reloadData];

而不是:[tableView beginUpdates];[tableView endUpdates];

需要代码:

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

    if (editingStyle == UITableViewCellEditingStyleDelete) 

    [tableData removeObjectAtIndex:indexPath.row];
[arrayA setValue:tableData ForKey:@"Hostname"];
        [arrayA writeToFile:plistPath atomically: TRUE];
        [self.tableView reloadSections:[NSIndexSet  indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];

    
    

【讨论】:

这会引发一个新错误。 *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[__NSArrayI removeObjectAtIndex:]:无法识别的选择器发送到实例 0x8b520d0”

以上是关于从 uitableview 中删除 + 写入 plist 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

从 UITableView 中删除 UITableViewCell

PL-SQL 从对象表中删除项目

尝试从 UITableView 中删除行时断言失败

使用 NSFetchedResultsController 从 UITableView 中删除

iOS - 从 UITableView 中删除行没有动画

从 UITableView 中删除行会导致部分标题问题?