Одновременные загрузки NSURLD - PullRequest
2 голосов
/ 07 ноября 2010

У меня установлено приложение Cocoa Mac для загрузки файлов в определенную папку с помощью NSURLDownload. Это прекрасно работает с одной загрузкой за раз. Тем не менее, если я попытаюсь начать несколько загрузок, все, кроме последней, сразу же потерпит неудачу.

Есть ли способ использовать NSURLDownload для нескольких одновременных загрузок? Или что может быть хорошим способом поставить в очередь несколько URL-адресов для загрузки по порядку? Или есть более подходящий способ сделать это (NSURLConnection казалось возможным, но я не был уверен, смогу ли я установить местоположение и имя файла для загрузки, как я могу с NSURLDownload)?

Ответы [ 3 ]

2 голосов
/ 08 ноября 2010

Каждый NSURLDownload представляет один экземпляр загрузки.Вы, вероятно, пытаетесь использовать один и тот же раз несколько раз.Это изначально асинхронная система, которая уже использует фоновые потоки.Вот пример, основанный на примере кода Apple:

 - (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];
}

Если вы попытаетесь использовать один и тот же NSURLDownload для обоих запросов NSURL, тогда оно прервет предыдущее соединение.

0 голосов
/ 08 ноября 2010

Я бы второй использовал NSOperation, если вы на 10,5+ или выше.Вы можете просто добавить 1 операцию в очередь для каждой загрузки.Или вы можете просто использовать sendSynchronous request и использовать его с методом addSOperationWithBlock (10.6+) в NSOperationQUeue, а затем в своем блоке, который вы выбрасываете в очередь, вы можете просто использовать [[NSOperationQueue mainQueue] addOperationWithBlock: ^ {когда вы делаете кодвам нужно выполнить или просто периодически обновлять пользовательский интерфейс в главном потоке, например ...

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

вам просто нужно делать это для каждой загрузки.

0 голосов
/ 08 ноября 2010

Если вы нацелены на 10,5+, вам стоит взглянуть на NSOperation. Это должно позволить вам создать общее решение для одной загрузки, а затем использовать встроенные средства очереди для управления зависимостями, если вам требуется, чтобы определенные операции заканчивали загрузку до того, как начнутся другие.

Имейте в виду, что эти API часто ожидают, что задействованные методы делегатов будут выполняться в главном потоке, поэтому вам необходимо убедиться, что это происходит, если вы работаете с асинхронными API, которые работают через методы делегатов. (Вы можете сделать это довольно просто, используя executeSelectorOnMainThread: и друзей)

...