2009-05-07 6 views
2

私は最近、Apple SDK(iPhone用など)を学んでいて、理解できないものを見つけました。 "Using NSURLConnection"の文書でNSURLConnectionのApple SDKドキュメントに間違いや混乱がありますか?

私は奇妙な説明とサンプルコードを発見しました。最初に、それは言う:

ダウンロードは、initWithRequest:delegate:メッセージを受信するとすぐに開始します。デリゲートがconnectionDidFinishLoading:またはconnection:didFailWithError:メッセージを受信する前にいつでも取り消すことができます。

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

    if (theConnection) { 

    // Create the NSMutableData that will hold 

    // the received data 

    // receivedData is declared as a method instance elsewhere 

    receivedData=[[NSMutableData data] retain]; 

    } else { 

    // inform the user that the download could not be made 

    } 

だから、ダウンロードは、すぐtheConnectionが初期化されるよう別のスレッドですぐに開始しなければならないように私には思える:

次に、それは以下のコードを示します。これは、コードが非ブロックであり、デリゲート(この場合はself)にメッセージを返信するため、明らかです。しかし、の後にreceivedDataの(自動解放スタイルの)割り当てがになると、他のスレッドが開始されます。これは安全でない競争状態ではありませんか?非常に高速なサーバ応答(ループバックデバイスなど)や不運なスレッドスケジューリングの場合に、クラッシュ、メモリリーク、またはデータの損失を招くことはありませんか? theConnectionが初期化される前にreceivedDataを割り当てるのが理にかなっていないでしょうか?

私はこのコードで混乱しています。誰かが私にとってそれを見せてくれることを願っています。すべての情報について おかげで、

ルディCilibrasi

答えて

6

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

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

私はこの例が、無関係なコードを多用してプレゼンテーションを混同しないように、可能な限り短くする方法を書いていると思います。 the documentation for NSURLConnectionから

NSURLConnection’s delegate methods allow an object to receive informational callbacks about the asynchronous load of a URL request. Other delegate methods provide facilities that allow the delegate to customize the process of performing an asynchronous URL load.

Note that these delegate methods will be called on the thread that started the asynchronous load operation for the associated NSURLConnection object.

+0

これは意味があります。私の研究のために、すべての委任メッセージがメインスレッドを通じて送信されるという主張をサポートするURLを教えてください。ヘルプと情報をありがとう。 –

+1

また、NSURLConnectionの委譲メッセージは実行ループによってマーシャリングされるため、制御が返された後にのみ発生することがあります。 – rpetrich

+0

Mark Besseyとrpetrichのおかげで大変感謝しています。これは今私にとっては明瞭で、私はそれを感謝します。 –

2

ここには競合状態がありません。 NSURLConnectionNSRunLoopを使用してイベントを送出します。したがって、次のイベントループが始まるまで、データは到着しません。

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

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

+0

これは、実際に何かに応答する前に私のブラウザウィンドウを開いたままにしておくように教えてくれるでしょう....はい、正解を持っているマークを完全に繰り返しました。 –

+0

Upvoted、NSRunLoopに関する詳細をいくつか追加しています。 –

+0

ありがとうございます。私はもともと何か他のものを探すこのスレッドに迷い込んでいましたが、興味深い質問がいくつか提起されました。あなたの答えはよく書かれ、有益で楽しいものでした。私は最後の行が一番好きですあるスレッドが別のスレッドで事態を起こさずにイベントを引き起こす方法について私自身の突発的な考えに対処しました(私は思慮深いと思っていましたが、協調的には意味があります)。 – RonLugge

関連する問題