5

IPhone アプリケーションを設計しています。ユーザーが何かを検索します。ネットからデータを取得します。次に、テーブルを更新します。

擬似コードは次のようになります

[DoThisAtbackground ^{
  LoadData ();
  [DoThisAtForeground ^{
    UpdateTableAndView();
  }];
}];

最初の検索が完了する前に、ユーザーが別の検索を行った場合はどうでしょうか。

問題を解決するための業界標準の方法は何ですか?

  1. まだ実行中のスレッドを追跡し、すべてのスレッドが終了したときにのみテーブルを更新しますか?
  2. スレッドが終了するたびにビューを更新しますか?

これをどのように正確に行うのですか?

4

3 に答える 3

2

リモート サーバーに対してデータの REST 要求を実行している場合は、いつでも要求をキャンセルして、テーブルを更新せずに新しい要求を開始することができます。完了する時間があるリクエストは UI を更新し、他のリクエストは更新しません。たとえば、ASIHTTPRequest を使用します。

- (void)serverPerformDataRequestWithQuery:(NSString *)query andDelegate:(__weak id <ServerDelegate)delegate {
  [currentRequest setFailedBlock:nil];
  [currentRequest cancel];
  currentRequest = [[ASIHTTPRequest alloc] initWithURL:kHOST];
  [currentRequest startAsynchronous];
}

ローカルの SQLite データベースについても回答が必要な場合はお知らせください。これははるかに複雑です。

于 2012-09-09T12:39:16.710 に答える
2

iOS Human Interface Guidelinesをご覧になることをお勧めします。Apple は、すべてのアプリケーションがほぼ同じように動作することが非常に重要であると考えているため、この種の問題に関する詳細なドキュメントを作成しました。

ガイドラインには、質問に関連する 2 つの事項があります。

  • 検索を迅速かつやりがいのあるものにする : 「可能であれば、ユーザーの入力中にリモート データもフィルター処理します。ユーザーの入力をフィルター処理することで検索エクスペリエンスが向上しますが、必ずユーザーに通知し、応答時間が長くなる可能性がある場合はオプトアウトする機会を与えてください。結果を 1 ~ 2 秒以上遅らせるためです。」
  • フィードバック: 「フィードバックは、人々の行動を認識し、処理が行われていることを保証します。人々は、コントロールを操作するときに即時のフィードバックを期待し、長時間の操作中にステータスの更新を高く評価します。」

もちろん、これらのガイドラインには多くのナンセンスがありますが、上記の点は実際に従うべきだと思います. ユーザーとして、検索時に何かが起こることを期待しています。スレッドが終了するたびにビューを更新すると、ユーザーは最速の応答を確認できます。はい、それはユーザーが望んでいない結果かもしれませんが、何かが起こっています! たとえば、iOS の Safari Web ブラウザを見てみましょう。Google オートコンプリートは、検索クエリの入力が終わったときだけでなく、入力中にも結果を表示します。

したがって、2番目のオプションを使用するのが最善だと思います。

于 2012-09-09T12:34:28.703 に答える
0

保留中のすべての操作をキャンセルするために使用できますNSOperationQueueが、それでも既存の操作はキャンセルされません。既存の操作をキャンセルするには、まだ何かを実装する必要があります...これは、キュー内の操作を早期に中止するためにも機能します。

私のユースケースに、より適した他の利点がない限り、通常はストレート GCD を好みますNSOperationQueue

また、ロードに外部キャンセル メカニズムがある場合は、保留中の I/O 操作をキャンセルする必要があります。

操作が独立している場合は、他のリクエストがキャンセルされているときに新しいリクエストを同時に実行できるようにするため、同時キューを検討してください。

また、それらがすべて I/O である場合はdispatch_io、スレッドをブロックする代わりに使用できるかどうかを検討してください。モンクが言うように、「あなたは後で私に感謝します.

次のようなことを考えてみましょう:

- (void)userRequestedNewSearch:(SearchInfo*)searchInfo {
    // Assign this operation a new token, that uniquely identifies this operation.
    uint32_t token = [self nextOperationToken];

    // If your "loading" API has an external abort mechanism, you want to keep
    // track of the in-flight I/O so any existing I/O operations can be canceled
    // before dispatching new work.

    dispatch_async(myQueue, ^{
        // Try to load your data in small pieces, so you can exit as early as
        // possible.  If you have to do a monolithic load, that's OK, but this
        // block will not exit until that stops.  
        while (! loadIsComplete) {
            if ([self currentToken] != token) return;
            // Load some data, set loadIsComplete when loading completes
        }

        dispatch_async(dispatch_get_main_queue(), ^{
            // One last check before updating the UI...
            if ([self currentToken] != token) return;

            // Do your UI update operations
        });
    });

}

最後に送信された操作以外の操作は早期に中止されます。使用したNSOperationQueue場合は呼び出すことができますcancelAllOperationsが、現在実行中のものを早期に中止するには、同様のメカニズムが必要です。

于 2012-09-09T13:33:00.903 に答える