2

sendAsynchronousRequest:queue:completionHandler:メソッド(NSURLConnectionクラス)に関連する正しい構成をセットアップするのにいくつかの困難があります。

私のシナリオは次のとおりです。

さまざまな を管理するシングルトン クラスをセットアップしましたNSURLConnection。このシングルトン インスタンスには、Web サーバーにリクエストを送信し、文字列パスを取得するNSOperation Queue( と呼ばれるdownloadQueue) があります (1)。完了したら、パスを使用して Web サーバー内でファイルをダウンロードします (2)。最後に、ファイルが正しくダウンロードされたら、UI を更新する必要があります (3)。

最初のリクエスト、つまりパスをダウンロードできるリクエストだけを見つけました。残りの 2 つの手順を実行する方法を教えてください。

ここでいくつか質問があります:

  • ダウンロード キュー ( downloadQueue) はメインのキューではありません。そのキューで新しい NSURLConnection を開くことはできますか? 言い換えれば、それは正しいですか?(コード スニペットのコメントを参照)

  • 前の質問が正しければ、メイン キューを取得して UI を更新するにはどうすればよいですか?

ここで、最初のステップを実行するために使用するコード スニペットdownloadQueueは、アクセサー メソッド ( @property/ @synthesized) を介して取得できるインスタンス変数です。

// initializing the queue...
downloadQueue = [[NSOperation alloc] init];    

// other code here...
[NSURLConnection sendAsynchronousRequest:urlRequest queue:[self downloadQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

    if([data length] > 0 && error == nil) {

        // here the path (1)
        // how to perform a second connection?
        // what type of queue do I have to use?              
    }
}];
4

2 に答える 2

5

You're on the right track for performing your first download.

In the completion handler block after the first download, you're computing the URL that you'll need for a second download, right? Then you can perform that second download the same way: call +[NSURLConnection sendAsynchronousRequest:...] again with the new URL and the same queue. You can do this within the completion block for the first download.

To update the UI after the second download is done, switch to the main queue within the completion block for that download. You can do this with dispatch_async() or dispatch_sync() (in this case it doesn't matter which because you don't have further work to do on the download queue) and dispatch_get_main_queue(), or with -[NSOperationQueue addOperationWithBlock:] and +[NSOperationQueue mainQueue].

Your code should look something like this:

// init download queue
downloadQueue = [[NSOperationQueue alloc] init];    

// (1) first download to determine URL for second
[NSURLConnection sendAsynchronousRequest:urlRequest queue:[self downloadQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    if([data length] > 0 && error == nil) {
        // set newURLRequest to something you get from the data, then...
        // (2) second download
        [NSURLConnection sendAsynchronousRequest:newURLRequest queue:[self downloadQueue] completionHandler:^(NSURLResponse *newResponse, NSData *newData, NSError *newError) {
            if([newData length] > 0 && newError == nil) {
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                    // (3) update UI
                }];
            }
        }];
    }
}];
于 2012-04-17T21:43:11.063 に答える
1

私の知る限り、UIを更新するには、メインスレッドでそれを行う必要があります。UI は他のスレッドから更新できますが、それらの更新は完全に信頼できるものではありません。私がまとめたアプリで、Web サービスにリクエストを行い、dispatch_async() を使用してメイン キューにアクセスし、その呼び出しから (私の場合はテーブル ビューを) 更新します。

dispatch_async(dispatch_get_main_queue(), ^{
    //block to be run on the main thread
    [self.tableView reloadData];
});

これが役立つことを願っています。

于 2012-04-17T20:21:52.037 に答える