私のアプリケーションに行を追加した後に、「無効な更新:セクション0の行数が無効です...」というUITableViewControllerがあります。つまり、%0.2のセッションでしか発生しません。私たちのアプリは、数百万のセッションを持ち、クラッシュが増えています。行を追加しているときにUITableViewがクラッシュする
フローは単純です。これは、ユーザーの音楽と動画のカタログを照合する機能の一部です。バックグラウンドスレッドは、一連の要求を行います。リクエストが消え、結果が返ってきたら、それらの結果がタブのテーブルビューに追加されます。リクエストはバッチで処理され、結果の行がたくさん追加されます。したがって、バッチが入った後にreloadDataを呼び出すのではなく、正しく追加する必要がありました。素晴らしいですが、時にはクラッシュします。
このデバイスを1回再生することができました。シミュレータでこれまでに起こったことはありません。私が知る限り、クラッシュは合理的にランダムですが、ほとんどが3gsで起こります。いくつかのクラッシュの数は4から来ています。
ここにコードがあります。応答が戻ってきます。この場合、allMatchesはこれまでのすべてのマッチ(テーブルのデータソース)です。 batchMatchesは新しいアーティストの数です。どちらも配列です:
[self.tableView beginUpdates];
NSMutableArray *paths = [[NSMutableArray alloc] init];
for (int i = [allMatches count] - [batchMatches count]; i < [allMatches count]; ++i) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
[paths addObject: indexPath];
}
[self.tableView insertRowsAtIndexPaths:paths withRowAnimation:NO];
[self.tableView endUpdates];
[paths release];
コードはかなりシンプルです。最後に、結果ごとに行を追加するだけです。削除しないでください。完全な例外メッセージの例は、「無効な更新:セクション0の行数が無効です。更新後の既存のセクション(131)に含まれる行の数は、更新前のそのセクションに含まれる行の数と等しくなければなりません131)、そのセクションから挿入または削除された行の数をプラスまたはマイナスし(20が挿入され、0が削除されます)、そのセクションの内外に移動された行の数をプラスまたはマイナスします(0は移動、0は移動)。実際のクラッシュレポートには数字がすべて載っているので、特定のバッチ番号ではありません。
私が言ったように、それはほとんど常に動作します。通常、3GSでクラッシュします。これがフレームワークのバグかもしれないかと思います。私はいつでも各バッチが返った後にreloadDataを呼び出すことができましたが、そのたびにテーブルのセルが醜く点滅します。私は例外をトリガし、それはテーブルが死んでいるので、私はキャッチブロックのフォールバックとしてreloadDataを使ってtry/catchを行うことができませんでした。
誰でも光を放つことはできますか?この投稿の長さにお詫び申し上げます。
EDIT:サーバー要求はNSOperationQueueを使用して行われるため、バックグラウンドスレッド上にあります。応答が返ってくると、メインスレッドに通知がポストされ、テーブルコードが実行されます。通知は次のように掲載されます。
NSNotification *notification = [NSNotification notificationWithName:notificationName object:self];
[self performSelectorOnMainThread:@selector(postNotification:) withObject:notification waitUntilDone:NO];
ポストnotificiation単に[:通知[NSNotificationCenter defaultCenter] postNotification]のラッパーです。したがって、テーブルコードはメインスレッド上になければなりません。
お返事ありがとうございました。私はテーブルコードがメインスレッド上で動作することを説明するために私の質問を追加しました。バックグラウンドで実行されるのはサーバー通信だけです。私はあなたとは異なるアプローチをとった。私はNSOperationQueueを使用してサーバー通信を実行します。次に、NSNotificationがperformSelectorOnMainThread経由でbgスレッドから送信されます。したがって、noitifcationはメインスレッドを送信します。ViewControllerはその通知を受け取ります。この通知はメインスレッド上にあり、テーブルを更新します。私のアプローチとあなたの問題の間に何か問題はありますか?再度、感謝します。 –
私は両方のアプローチの違いを実際に見ることはできません。両方ともメインスレッド上でコードを非同期に実行します。テーブルを更新している間、バックグラウンドスレッドによってデータ配列を変更できないようにしてください。安全な側になるためには、同期通知を送信することができます。 waitUntilDoneをYESに設定するだけです。 – Felix
DUDE、あなたはそれを解決したかもしれないと思います。私はwaitUntilDoneをNOに設定しました。完璧な意味合い:通知の投稿、テーブルの更新が開始され、別の通知が発生し、テーブルが2回目の更新を開始してクラッシュします。私は次のアップデートの後で確かに知っているだろうが、これは完璧な意味合いがあり、3gで起こったのはそのデバイスが最も遅いためである。ところで私はVEVOにいるので、もしあなたが好きならアプリをチェックしてください。再度、感謝します。あなたはロック! –