开发者

Simultaneous NSURLDownloads

开发者 https://www.devze.com 2023-01-24 02:36 出处:网络
I have a Cocoa Mac application set up to download files to a specific folder using NSURLDownload. This works great with a single download at a time. However, if I attempt to start multiple downloads,

I have a Cocoa Mac application set up to download files to a specific folder using NSURLDownload. This works great with a single download at a time. However, if I attempt to start multiple downloads, all but the last will fail immediately.

Is there any way to use NSURLDownload for multiple simultaneous downloads? Or what would be a good way to queue up multiple URLs to be downloaded in order? Or is there a more appropriate way to accomplish this (NSURLConnection seemed possible but I was unsure if I could set the download location an开发者_StackOverflow中文版d filename as I can with NSURLDownload)?


Each NSURLDownload represents a single downloading instance. You're probably trying to reuse the same one multiple times. It's an inherently asynchronous system that already used background threads. Here's an example based on Apple's sample code:

 - (void)startDownloadingURL:sender
{
    // Create a couple requests.
    NSURLRequest *requestOne = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com"]
                                                cachePolicy:NSURLRequestUseProtocolCachePolicy
                                            timeoutInterval:60.0];

    NSURLRequest *requestTwo = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://stackoverflow.com"]
                                                cachePolicy:NSURLRequestUseProtocolCachePolicy
                                            timeoutInterval:60.0];

    // Create two download instances
    NSURLDownload *downloadOne = [[NSURLDownload alloc] initWithRequest:requestOne delegate:self];
    NSURLDownload *downloadTwo = [[NSURLDownload alloc] initWithRequest:requestTwo delegate:self];

    if (downloadOne) {
        // Set the destination file.
        [downloadOne setDestination:@"/tmp" allowOverwrite:YES];
    } else {
        // inform the user that the download failed.
    }
    if (downloadTwo) {
        // Set the destination file.
        [downloadTwo setDestination:@"/tmp" allowOverwrite:YES];
    } else {
        // inform the user that the download failed.
    }
}


- (void)download:(NSURLDownload *)download didFailWithError:(NSError *)error
{
    // Release the connection.
    [download release];

    // Inform the user.
    NSLog(@"Download failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSErrorFailingURLStringErrorKey]);
}

- (void)downloadDidFinish:(NSURLDownload *)download
{
    NSLog(@"The download %@ has finished.", download)

    // Release the download connection.
    [download release];
}

If you attempt to use the same NSURLDownload for both NSURLRequests, then it will kill the previous connection.


I'd second using NSOperation if your on 10.5+ or greater. You could just throw 1 operation onto a queue for each download. Or you could even just use sendSynchronous request and use it with NSOperationQUeue's addOperationWithBlock (10.6+) method and then in your block you are throwing onto the queue you can just use [[NSOperationQueue mainQueue] addOperationWithBlock:^{ when you are doe with the code you need to execute or just periodically need to refresh the UI on the main thread, like so...

[myQueue addOperationWithBlock:^{
    //download stuff here...
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
         //update main thread UI
    }];
}];

you would just need to do this for each download.


If you're targeting 10.5+, you should look at NSOperation. It should allow you to build a generic solution for a single download, and then use the built-in queue facilities to manage dependencies if you require certain operations finish downloading before others begin.

Keep in mind that these APIs often expect delegate methods involved to be run on the main thread, so you'll need ensure that occurs if you're working with asynchronous APIs that function via delegate methods. (You can do this pretty simply by using performSelectorOnMainThread: and friends)

0

精彩评论

暂无评论...
验证码 换一张
取 消