2

私のiOSアプリケーションの1つのビューは、UISearchDisplayです。ユーザーが新しい文字を入力するたびにテーブルが再入力されるように、先行入力検索として設計しました。UISearchDisplayDelegateプロトコルメソッドを実装することでこれを行いました。

searchDisplayController:shouldReloadTableForSearchString:

このメソッドでは、提供された文字列を取得して、クエリURLに追加します。次に、新しいNSURLConnectionを作成し、新しい非同期リクエストを送信します。デリゲートメソッドを介してデータを受信して​​追加します。

connection:didReceiveData:

接続がデータのダウンロードを完了したら、次の方法で行います。

connectionDidFinishLoading

NSXMLParserのインスタンスにデータを渡します。受信するデータは、指定された文字列に一致するデータベース内のすべての連絡先のXMLファイルです。データの解析が終了したら、テーブルをリロードします。

私の問題:ユーザーがテキストを十分に速く入力すると、複数の接続タスクと解析タスクが同時に実行されます。データを追加して解析するNSMutableDataのインスタンスが1つあるため、これは問題です。うまくいけば、あなたは私がこれでどこに行くのかを見ることができます。

私の実装を改善したり、このクリティカルセクションの問題を解決したりするための提案はありますか?

4

2 に答える 2

0

NSXMLParser非同期ではありません。これは、デリゲートコールバックメソッドの使用が原因であると想定しているため、多くの人をつまずかせます。ただし、実際には、parseすべての解析が終了するまでメソッドは戻りません。

したがって、一度に複数の接続を実行している場合でも、自分でマルチスレッド化しない限り、複数の解析操作が発生することはありません。

複数の接続の問題を解決するには、接続ごとに1つのNSMutableDataを使用する代わりに、1つ使用するのはどうでしょうか。これを行うにはいくつかの方法があります。アイデアについては、次の質問に対する回答を確認することをお勧めします。

于 2012-07-13T11:40:35.463 に答える
-1

UISearchDisplayControllerを使用したキャンセル可能な非同期検索で説明されている優れた実装があります

ソリューションの要点は次のとおりです。

  • NSOperationQueue検索操作を実行するインスタンスを作成し、UISearchDisplayDelegate実装のプロパティに保存します。名前を付けましょうsearchQueue

  • メソッドを実装しsearchDisplayController:shouldReloadTableForSearchString:ます。このメソッドは、テーブルビューをリロードするようにインスタンスに通知するBOOL値を返すことに注意してください。UISearchDisplayControllerメソッドは次のように実装できます。

    -(BOOL)searchDisplayController:(UISearchDisplayController *)controller 
    shouldReloadTableForSearchString:(NSString *)searchString {
        if ([searchString isEqualToString:@""] == NO) {
            [self.searchQueue cancelAllOperations];
            [self.searchQueue addOperationWithBlock:^{
    
              NSArray *results = // fetch the results from
              // somewhere (that can take a while to do)
    
              // Ensure you're assigning to a local variable here.
              // Do not assign to a member variable.  You will get
              // occasional thread race condition related crashes 
              // if you do.            
    
              [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                // Modify your instance variables here on the main
                // UI thread.
                [self.searchResults removeAllObjects]; 
                [self.searchResults addObjectsFromArray:results];
    
                // Reload your search results table data.
                [controller.searchResultsTableView reloadData];
              }];
            }];
    
            return NO;
    
        } else {
            [self.searchResults removeAllObjects];
            return YES;
        }
    }
    
  • ユーザーが検索UIを閉じたときに、保留中の操作をキャンセルすることを忘れないでください。

         - (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
             [self.searchQueue cancelAllOperations];
         }
    
于 2014-06-29T14:50:04.757 に答える