2

最近、Apple SDK (iPhone など用) を学習していて、理解できないことに遭遇しました。http://developer.apple.com/documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.htmlの「NSURLConnection の使用」のドキュメント

奇妙な説明とサンプル コードを見つけました。まず、次のように述べています。

ダウンロードは、initWithRequest:delegate: メッセージを受信するとすぐに開始されます。デリゲートが connectionDidFinishLoading: または connection:didFailWithError: メッセージを受信する前に、接続にキャンセル メッセージを送信することにより、いつでもキャンセルできます。

次に、次のコードを示します。

  NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

  if (theConnection) {

    // 保持する NSMutableData を作成します

    // 受信データ

    // receivedData は別の場所でメソッド インスタンスとして宣言されています

    receivedData=[[NSMutableData データ] 保持];

  } そうしないと {

    // ダウンロードできなかったことをユーザーに通知します

  }

そのため、接続が初期化されるとすぐに、別のスレッドでダウンロードをすぐに開始する必要があるように思えます。これは明らかです。なぜなら、このコードは非ブロッキングであり、メッセージをデリゲート (この場合は self) に送り返すからです。それでも、(autorelease スタイルの) receivedData の割り当ては、他のスレッドが開始された後に発生します。これは危険な競合状態ではありませんか? これは、サーバーの応答が非常に高速な場合 (ループバック デバイスなど)、または不運なスレッド スケジューリングの場合に、クラッシュ、メモリ リーク、またはデータの損失を引き起こす可能性はありませんか? theConnection が初期化される前に receivedData を割り当ててから、上記の else の場合にそれを解放する方が理にかなっているでしょうか?

私はこのコードにとても混乱しています。誰かが私のためにいくつかの光を当ててくれることを願っています. 情報をありがとう、

ルディ・チリブラシ

4

2 に答える 2

6

競合状態はありません。ダウンロードは別のスレッドでバックグラウンドで開始されますが、ダウンロードの進行状況を通知するためにデリゲートに送信されるメッセージは、ダウンロードを開始したスレッドで常に呼び出されます。

より明確な場合は、接続が作成される前に NSData を確実に割り当てることができます。保存するデータがない限り NSData が割り当てられないようにする場合は、connection:didReceiveData: メソッドで割り当てることもできます。

この例は、プレゼンテーションを多くの無関係なコードと混同しないように、できるだけ短くするように書かれていると思います。

NSURLConnection のドキュメントから:

NSURLConnection のデリゲート メソッドを使用すると、オブジェクトは URL 要求の非同期ロードに関する情報コールバックを受け取ることができます。他のデリゲート メソッドは、デリゲートが非同期 URL ロードを実行するプロセスをカスタマイズできるようにする機能を提供します。

これらのデリゲート メソッドは、関連する NSURLConnection オブジェクトの非同期ロード操作を開始したスレッドで呼び出されることに注意してください。

于 2009-05-07T03:21:22.120 に答える
2

ここには競合状態はありません。NSURLConnectionを使用しNSRunLoopてイベントをディスパッチします。したがって、次のイベントループが開始されるまで、データは到着しません。

これはconnection:didReceiveData:、データが実際にいつ戻ってくるかに関係なく、次のイベントループまで呼び出しが発生しないことを意味connection:didReceiveData:し、ロードを開始したスレッドで呼び出されます。したがって、この実行ループの残りの部分ですべてを順番に取得できます。「すぐに」とは、ここで「開始するために何もする必要がない」ことを意味します。

これは推測や変更可能な実装の詳細ではありません。これは、Cocoaの設計原則に基づいています。Cocoaを最もよく理解するために、ほとんどすべてがメインスレッドで発生すると仮定します。フレームワークは、実装の詳細としてスレッドを生成する場合がありますが、常にそうではないという幻想を提供します。したがって、非同期操作は、その性質上、常に後のイベントループに表示されます。協調的で、先見の明のないマルチタスクは、Cocoaの方法です。

于 2009-05-07T14:54:19.100 に答える