0

私が構築しているアプリには多くのテーブルがあります。最初の 15 行のデータをロードしています。ユーザーが下にスクロールすると、次の 15 行のバッチが取得されます。

「カウント」と「スキップ」を受け取る DBAccess 関数をいくつか作成しました。最初にテーブルをロードするとき、カウント = 15、スキップ = 0。ユーザーがスクロールするとき、カウント = 15、スキップ = [配列カウント];

コードは次のようなものです。

- (void)getDataWithCount:(NSInteger)count withSkip:(NSInteger)skip
{
    if (skip == 0)
        self.dataArray = [[NSMutableArray alloc]init];

    [DBAccess getData:self.dataArray withCount:count withSkip:skip handler:^(void)
    {
        if (no error)
            [table reloadData];
    }]; 
}

非常に遅いネットワーク接続で cellForRowAtIndexPath の範囲外の配列がクラッシュします (たとえば、空の配列を超えるインデックス 16。numberOfRowsInSection は [配列数] を返します)。

問題は次のとおりだと思います。

0) 画面に入ります。

1) 15 行をロードする

2) 下にスクロールして、別の 15 をロードします。接続が遅いため、sendAsynchronousRequest db 呼び出しからまだコールバックがありません

3) 別のビューコントローラーに移動します (つまり、画面を離れます。非同期で画面がフリーズしないため、これを行うことができます)。

4) 画面に戻ります。初期画面をロードするとskip = 0が設定されるため、変更可能な配列が初期化され、データベースにヒットします

5) 手順 2 でヒットしたデータベースが返されます。私の可変配列は、ステップ 4 からゼロに設定されました。テーブルをリロードするとき、配列が if(skip == 0)initialise から空になったときに、self.dataArray objectAtIndex:16 などを取得しようとしています。

これは正しいと思いますか?numberOfRowsInSection が [array count]; を返す場合、配列が範囲外になる他の理由はありますか? これを修正するための好ましい方法はありますか?

4

1 に答える 1

0

提供された限られた情報について言うのは難しいですが、ポイント5を調整するのは難しいです.配列は再初期化されていますが、dbリクエストはまだ進行中です. テーブルをサポートするモデル オブジェクトがリセットされた場合、データベース クエリはまだ実行されていません。また:

  • モデル オブジェクトが範囲外になったら、非同期データ リクエストをキャンセルする必要があります (たとえば、操作がプロパティとして設計されている場合は、GCD の代わりにキャンセル可能な操作キューを使用します)。また

  • そのモデル オブジェクトをなんらかのキャッシュ メカニズムで保持する必要があります。これにより、非同期データ リクエストが完了し、手順 4 でコントローラーに戻ったときに、データがキャッシュされて表示できるようになります。

問題の他の潜在的な原因に関しては、非同期データ更新プロセスが本当にスレッドセーフであるかどうか疑問に思います。非同期で更新しているプロパティとのやり取りを同期していますか? この同期は、通常、何らかのロック メカニズムまたは専用のシリアル キュー(またはリーダー/ライター パターンでの同時キューの使用) を介して行われます。スレッドセーフは重要な問題であり、そのスコアにどれだけ自信があるのだろうか.

于 2013-07-03T08:36:23.970 に答える