1

を使用していくつかのファイルをダウンロードしようとしていますNSURLConnection:

- (void)startDownload {
  NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
  [req addValue:@"Basic XXXXXXXXXXXXXX=" forHTTPHeaderField:@"Authorization"];
  connection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response {
  filepath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:save_name];
  [[NSFileManager defaultManager] createFileAtPath:filepath contents:nil attributes:nil];
  file = [[NSFileHandle fileHandleForUpdatingAtPath:filepath] retain];
  [file seekToEndOfFile];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
  [file seekToEndOfFile];
  [file writeData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection*)connection {
  [file closeFile];
 }

私のファイルは非常に大きいので、ダウンロードしたすべての部分をディスクに保存する必要があり、それらを RAM に保存することはできません。問題は、複数のダウンロードをどのように処理できるかということです。

前回のダウンロードが で終わってから次のダウンロードを開始しようと考えていましたが- (void)connectionDidFinishLoading:、それは最善の方法ではないようです。助言がありますか?

4

3 に答える 3

2

複数のダウンロードの場合は、複数NSURLConnectionの を使用します。

各デリゲート メソッドで、それが参照する接続が渡されることに注意してください。作成したすべての接続を保存する必要があるだけです (プロパティとして、または配列内など、設計によって異なります)。次に、 を実装するときに、保存されている各接続とパラメータをconnection: didReceiveData:比較 ( を使用==) することで、どの接続が何らかのデータを受信したかを確認でき、それに応じてデータを処理できます。

于 2012-10-15T12:39:26.907 に答える
2

NSURLConnection を使用する場合は、接続をラップしてディスクへの書き込みを処理する独自のダウンロード オブジェクトを作成することをお勧めします。

次のように、完成したファイルを入れるファイル名とファイルを取得する URL でオブジェクトを初期化します。

MyDownloadObject *o = [[MyDownloadObject alloc] initWithFilename:filename URL:url];
o.delegate = self;

各ダウンロードオブジェクトは、質問とほぼ同じコードを使用して、独自の NSURLRequest および NSURLConnection を処理します:)

完了すると、ダウンロードされたことをView Controllerに通知します(おそらくデリゲートメソッドを介しますが、通知も同様に機能します)。その後、どのファイルが終了したかをデリゲート メソッドから知ることができます。

- (void)myDownloadObjectFinishedDownload:(MyDownloadObject *)o {
    NSLog(@"File from %@ has been stored at %@", o.URL, o.filename);
}

MyDownloadObject を NSOperation のサブクラスにした場合、NSOperationQueue を使用して同時ダウンロードを制限し、全体的な進行状況などを監視できます。


サード パーティのライブラリを使用しても構わない場合は、ASIHTTPRequest を選択することをお勧めしますが、現在は開発されていないことに注意してください。スタック オーバーフローに関する他の人は、代わりに使用できるより優れた最新のライブラリを推奨するのではないかと思います。

于 2012-10-15T12:46:19.013 に答える
1

これは私が思いついたものです:

  • downloadQueue という名前の変更可能な配列を作成します
  • 現時点でダウンロード接続が実行されているかどうかを確認し、実行されている場合は接続をキューに入れます
  • 接続が終了したら、キューを確認し、キューにメンバーがいる場合はキューを実行します

実装: (重要な部分にマークを付けます。追加のコントロールについては、各ステップを確認してください)

プライベートメンバーとして;

...
@property (nonatomic, retain) NSURLConnection *downloadConnection;
@property (nonatomic, retain) NSMutableArray *downloadQueue;
...

次のような機能を変更します。

- (void)startDownload {
  NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
  [req addValue:@"Basic XXXXXXXXXXXXXX=" forHTTPHeaderField:@"Authorization"];

  if (self.downloadConnection)
  {
       if (!self.downloadQueue) self.downloadQueue = [[NSMutableArray alloc] init];
       [self.downloadQueue addObject:request];
       return;
  }
  // else just run your connection
  self.downloadConnection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES];
}

    - (void)connectionDidFinishLoading:(NSURLConnection*)connection {
  [file closeFile];
  // nil your connection
  self.downloadConnection = nil;
  // check the state of your queue
  [self checkQueue];
 }


 -(void)checkQueue
{
    if (self.downloadQueue)
    {
          if (self.downloadQueue.count > 0)
          {
                NSURLRequest *queueLastObject = [self.downloadQueue lastObject];
                // call the request with downloadConnection and remove it from the queue...
          }
    }
}

注:このコードは、実装のアイデアを指定することのみを目的としており、使用するには編集する必要があります。任意の時点で問題が発生した場合は、お知らせください。コードを更新します。

于 2012-10-15T12:51:32.537 に答える