ファイルをダウンロードする同期メソッド (NSData の initWithContentsOfURL および NSURLConnection の sendSynchronousRequest) を正常に使用するアプリがありますが、大きなファイルをサポートする必要があります。これは、ビットごとにディスクにストリーミングする必要があることを意味します。ディスクへのストリーミングと非同期化は完全に正統な概念であるべきですが、Apple の API では、ストリーミングするために非同期化を余儀なくされています。
明確にするために言うと、私はより大きなファイルのダウンロードを可能にすることを任されており、アプリ全体を再設計してより非同期対応にすることを任されていません。リソースがありません。しかし、再設計に依存するアプローチが有効で優れていることは認めます。
だから、私がこれを行うと:
NSURLConnection* connection = [ [ NSURLConnection alloc ] initWithRequest: request delegate: self startImmediately: YES ];
..私は最終的に自分自身でdidReceiveResponseとdidReceiveDataを呼び出しました。優秀な。しかし、私がこれをやろうとすると:
NSURLConnection* connection = [ [ NSURLConnection alloc ] initWithRequest: request delegate: self startImmediately: YES ];
while( !self.downloadComplete )
[ NSThread sleepForTimeInterval: .25 ];
... didReceiveResponse と didReceiveData は呼び出されません。そして、私はその理由を理解しました。奇妙なことに、非同期ダウンロードは、私が使用しているのと同じメイン スレッドで行われます。したがって、メイン スレッドをスリープ状態にすると、作業を行っているものもスリープ状態になります。とにかく、ここで必要なことを達成するために、NSURLConnection に別の NSOperationQueue を使用するように指示したり、dispatch_async を実行して接続を作成して手動で開始したりするなど、いくつかの異なる方法を試しました (これがどのように機能しないのかわかりません-私はそれを正しく行っていなかったに違いありません)が、何も機能していないようです。編集:私が正しく行っていなかったのは、実行ループがどのように機能するか、およびそれらをセカンダリ スレッドで手動で実行する必要があることを理解することでした。
ファイルのダウンロードが完了するまで待つ最善の方法は何ですか?
編集 3、作業コード: 次のコードは実際に動作しますが、より良い方法があれば教えてください。
接続を設定し、ダウンロードの完了を待機する元のスレッドで実行されるコード:
dispatch_queue_t downloadQueue = dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 );
dispatch_async(downloadQueue, ^{
self.connection = [ [ NSURLConnection alloc ] initWithRequest: request delegate: self startImmediately: YES ];
[ [ NSRunLoop currentRunLoop ] run ];
});
while( !self.downloadComplete )
[ NSThread sleepForTimeInterval: .25 ];
接続イベントに応答する新しいスレッドで実行されるコード:
-(void)connection:(NSURLConnection*) connection didReceiveData:(NSData *)data {
NSUInteger remainingBytes = [ data length ];
while( remainingBytes > 0 ) {
NSUInteger bytesWritten = [ self.fileWritingStream write: [ data bytes ] maxLength: remainingBytes ];
if( bytesWritten == -1 /*error*/ ) {
self.downloadComplete = YES;
self.successful = NO;
NSLog( @"Stream error: %@", self.fileWritingStream.streamError );
[ connection cancel ];
return;
}
remainingBytes -= bytesWritten;
}
}
-(void)connection:(NSURLConnection*) connection didFailWithError:(NSError *)error {
self.downloadComplete = YES;
[ self.fileWritingStream close ];
self.successful = NO;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
self.downloadComplete = YES;
[ self.fileWritingStream close ];
self.successful = YES;
}