0

リモート Web サイトにアクセスしてNSURLConnectionコードを実行し、XML ファイルを保存するアプリがあります。次に、これらの XML ファイルにアクセスし、それらを解析して情報を取得します。ユーザー インターフェイスが適切に更新されないことを除けば、プロセスは正常に機能します。を通じてユーザーを最新の状態に保ちたいですUILabel。を使用してテキストを更新しようとしていますsetBottomBarToUpdating:。「Processing Please Wait...」に設定すると、初めて機能します。ただし、connectionDidFinishLoading:更新されません。NSURLConnection が別のスレッドで実行されておりdispatch_get_main_queue、メイン スレッドでの更新の試みが機能していないと考えています。これを解決するためにコードを変更するにはどうすればよいですか? ありがとう![より多くの情報/コードを含める必要がある場合は、お知らせください!]

myFile.m

NSLog(@"Refreshing...");

dispatch_sync( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
     [self getResponse:@"http://mylocation/path/to/file.aspx"];
});

[self setBottomBarToUpdating:@"Processing Please Wait..."];

queue = dispatch_queue_create("updateQueue", DISPATCH_QUEUE_CONCURRENT);

connectionDidFinishLoading:

if ([response rangeOfString:@"Complete"].location == NSNotFound]) {
  // failed
} else {
  //success
  dispatch_async(dispatch_get_main_queue(),^ {
       [self setBottomBarToUpdating:@"Updating Contacts..."];
  });

  [self updateFromXMLFile:@"http://thislocation.com/path/to/file.xml"];

  dispatch_async(dispatch_get_main_queue(),^ {
       [self setBottomBarToUpdating:@"Updating Emails..."];
  });

  [self updateFromXMLFile:@"http://thislocation.com/path/to/file2.xml"];  

}
4

3 に答える 3

1

私のconnectionDidFinishLoadingで:私は次のようなことを試みます:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^ {
    if ([response rangeOfString:@"Complete"].location == NSNotFound]) {
      // failed
    } else {
      //success
      dispatch_async(dispatch_get_main_queue(),^ {
           [self setBottomBarToUpdating:@"Updating Contacts..."];
      });

      [self updateFromXMLFile:@"http://thislocation.com/path/to/file.xml"];

      dispatch_async(dispatch_get_main_queue(),^ {
           [self setBottomBarToUpdating:@"Updating Emails..."];
      });

      [self updateFromXMLFile:@"http://thislocation.com/path/to/file2.xml"];  
    }
});

次に、すべてのファイルアクセスがバックグラウンドキューで行われるため、メインキューがロックされません。メインキューは、connectionDidFinishLoadingへのこの呼び出しをはるかに迅速に完了します。これは、代わりにすべてのハードワークをデフォルトキューにスローするため、UIへの更新のキューイングを受け入れる準備ができているはずです。これは、キューに入れたばかりのブロックを処理するときに、デフォルトのキューによって実行されます。

キューのハンドオーバーは

  • connectionDidFinishLoadへのメインスレッドコールバック:
  • メインスレッドを解放するデフォルトのグローバルキューへの迅速なハンドオフ
  • setBottomBarToUpdatingのメインキューへの最終的なハンドオフ:呼び出し
  • UIを適切に更新するためにメインスレッドでメインキューブロックを実行する
  • メインキューのブロックの最終的な完了
  • デフォルトキューのブロックの最終的な完了

同時実行性が向上し(マルチコアデバイスが優れている場合は優れています)、メインスレッドからI / Oの負担を取り除き(決して適切な場所ではありません)、代わりにユーザーインターフェイスの作業に集中するようになりました(そのための適切な場所)。

理想的には、メインスレッドからNSURLConnection実行ループを実行することもできますが、これで十分な場合があります。

于 2012-11-10T15:31:31.640 に答える
0

どの実行ループで NSURLConnection を実行していますか? それがメイン ループである場合は、setBottomBarToUpdating: 呼び出しを既に行っている作業の背後でキューに入れているため、UI の更新が表示されない理由が考えられます。

于 2012-11-08T16:57:58.237 に答える
0

performSelectorOnMainThread次のように試すこともできます。

if ([response rangeOfString:@"Complete"].location == NSNotFound]) {
                // failed
            } else {
                //success
                [self performSelectorOnMainThread:@selector(setBottomBarToUpdating) withObject:@"Updating Contacts..." waitUntilDone:false];

                [self updateFromXMLFile:@"http://thislocation.com/path/to/file.xml"];

                [self performSelectorOnMainThread:@selector(setBottomBarToUpdating) withObject:@"Updating Emails..." waitUntilDone:false];


                [self updateFromXMLFile:@"http://thislocation.com/path/to/file2.xml"];  

            }
于 2012-11-08T16:53:06.247 に答える