1528


もともとUITableViewControllerを使って問題なく動いていたテーブル画面を、UIViewController +
UITableViewを使って動くように書き換えています。（UITableViewControllerだといろいろな制限が多いので。）

概ねうまく動いているのですが、ただひとつ問題が起きてスタックしております。 スワイプしてセルを削除しようとするとクラッシュしてしまうのです。
解決方法ご教示いただけたらうれしいです。

エラー内容

[code]

    *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
    reason: 'Invalid update: invalid number of rows in section 1. 
     The number of rows contained in an existing section after the update (8) 
     must be equal to the number of rows contained in that section before the update (9),
     plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 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:
    
[/code]

ソースコード

[code]

    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (editingStyle == UITableViewCellEditingStyleDelete) {
    
            //[Parse] 該当データのIDを取得
            PFQuery *query = [PFQuery queryWithClassName:@"Item"];
    
            //[Parse]favoriteData配列のなかから、行数をベースに、該当データをdictionaryとして取り出す
            NSDictionary * deleteContent = [_favoriteData objectAtIndex:indexPath.row];
    
            //[Parse]該当データのIDを取り出す
            NSString *itemId = [deleteContent valueForKey:@"objectId"];
    
            //[Local]favoriteデータ配列から該当データを削除
            [_favoriteData removeObjectAtIndex:indexPath.row];
    
            //[Local]テーブルビューからRowを削除
            [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    
            //[Parse]IDをベースにデータを削除する
            [query getObjectInBackgroundWithId:itemId block:^(PFObject *deleteItem, NSError *error){
    
            //[Parse]オブジェクトを削除
            [deleteItem deleteInBackground];
    
            }];
    
    
        } 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.
        }
    }
    
[/code]

よろしくお願いいたします。


CC BY-SA 3.0
2014-12-11T17:34:28.090
1527
2014-12-12T02:54:25.513
682
question
ios tableview uitableview
tableViewのrowの削除ができません


テーブルの更新処理を

[code]

    [self.tableView beginUpdates];
    ...
    [self.tableView endUpdates];
    
[/code]

で更新処理を囲う必要があるかなと思います。

（ここからEDITまでの話はなかったことに）

それでもダメなら、おそらくなのですが、タイミング問題で、

[code]

    [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    
[/code]

を、

[code]

    [query getObjectInBackgroundWithId:itemId block:^(PFObject *deleteItem, NSError *error){
        //[Parse]オブジェクトを削除
        [deleteItem deleteInBackgroundWithBlock:^(BOOL succeeded, NSError *error){
            dispatch_async(
                dispatch_get_main_queue(),
                ^{
                     [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
                }
            );
        }];
    }];
    
[/code]

とするとどうなるでしょうか。
Parseを使ったことがないので、このコードが正しいかは定かではありませんが、単に、データが消されてからRowを消すということが実現できるならOKだと思います。
(asyncで云々というのはそもそもダメな例でした）

* * *

**EDIT 1**

なんだか、混乱させてしまって申し訳ありません。上のは忘れてください...

[code]

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
         NSLog(@"numberOfRowsInSection");
         return self.data.count;
    }
    
[/code]

としておいて、

[code]

    NSLog(@"endUpdates_before");
    [self.tableView endUpdates];
    NSLog(@"endUpdates_after");
    
[/code]

を呼び出すと、

[code]

    2014-12-12 04:22:36.534 temp[76478:2409696] endUpdates_before
    2014-12-12 04:22:36.534 temp[76478:2409696] numberOfRowsInSection
    2014-12-12 04:22:36.535 temp[76478:2409696] endUpdates_after
    
[/code]

という出力になります。で、たぶん、numberOfRowsInSectionでParseのcountを呼んでいるのだと思うのですが、getObjectInBackgroundWithIdでblock内で削除、だと、endUpdatesが呼ばれた段階で反映されていないのかなー、と思います。numberOfRowsInSectionが返している値が正しいかどうか確かめてみてください。

呼ばれる順番とかはbegin/endの中にあれば問題なくて、endが呼ばれる瞬間までに削除が反映されたcountが帰ってきていれば、NSInternalInconsistencyExceptionが消えると思います。


CC BY-SA 3.0
2014-12-11T17:56:10.523
1528
2014-12-11T19:29:56.457
2014-12-11T19:29:56.457
351
351
1527
answer


蛇足コメントかもしれませんが・・・・．

deleteRowsAtIndexPathsを呼ぶ前に，確実に，self.data.countが削除後の個数を返すようにしないといけないので，削除前に完全に同期で処理を行うのがいいと思います．

もし，非同期でやらなければならないなら．非同期処理の結果をコールバックで受け取ってから，削除アニメーションをかけるのがいいかと思いました．


CC BY-SA 3.0
2014-12-12T02:54:25.513
1529
2014-12-12T02:54:25.513
259
1527
answer