Пауза и возобновление ASINetworkQueue - PullRequest
1 голос
/ 29 января 2012

Я использую ASINetworkQueue для загрузки около 50 файлов в приложение для iPad. Я ищу способ позволить пользователю приостановить и возобновить очередь.

Документы ASIHTTP относятся к

[request setAllowResumeForFileDownloads:YES];

но это работает на уровне отдельного запроса, а не на уровне очереди. Поскольку ASINetworkQueue является подклассом NSOperationQueue, я также попробовал

[queue setSuspended:YES];

и, хотя это приостановит очередь, это не повлияет на текущие загрузки, оно просто ждет, пока они закончат, а затем приостанавливает очередь, что в моем случае означает много секунд между нажатием кнопки пользователем и очередью на самом деле пауза, а это не тот интерфейс, который мне нужен.

Кто-нибудь может предложить другой способ решения этой проблемы?

1 Ответ

0 голосов
/ 15 марта 2013

Мое решение ..

- (void) pause
{
    if(self.queue && self.queue.requestsCount>0)
    {
        NSLog(@"%@", self.queue.operations);

        for (ASIHTTPRequest * req in self.queue.operations) {
            req.userInfo = [NSDictionary dictionaryWithObject:@"1" forKey:@"ignore"];
        }

        [self.queue.operations makeObjectsPerformSelector:@selector(cancel)];

        [self.queue setSuspended:YES];

        for (ASIHTTPRequest * req in self.queue.operations) {
            ASIHTTPRequest * newReq = [[ASIHTTPRequest alloc] initWithURL:req.url];
            [newReq setDownloadDestinationPath:req.downloadDestinationPath];
            [newReq setTemporaryFileDownloadPath:req.temporaryFileDownloadPath];
//            [newReq setAllowResumeForFileDownloads:YES];
            [newReq setUserInfo:req.userInfo];
            [self.queue addOperation:newReq];

        }

    }
}

- (void) resume
{
    if(self.queue && self.queue.requestsCount>0)
    {
        [self _setupQueue];
        [self.queue go];
    }
}

- (void) _setupQueue
{
    [self.queue setShouldCancelAllRequestsOnFailure:NO];
    [self.queue setRequestDidStartSelector:@selector(downloadDidStart:)];
    [self.queue setRequestDidFinishSelector:@selector(downloadDidComplete:)];
    [self.queue setRequestDidFailSelector:@selector(downloadDidFailed:)];
    [self.queue setQueueDidFinishSelector:@selector(queueDidFinished:)];
    [self.queue setDownloadProgressDelegate:self.downloadProgress];
    [self.queue setDelegate:self];
    self.queue.maxConcurrentOperationCount = 3;
//    self.queue.showAccurateProgress = YES;
}

Во-первых, функция паузы отменяет все запущенные операции и создает новые запросы, помещая их в очередь.Затем функция возобновления возобновляет работу в очереди.Обратите внимание, что запрос не должен устанавливать setAllowResumeForFileDownloads: YES, в противном случае totalBytesToDownload будет неверно рассчитываться. Если allowResumeForFileDownloads = NO, его значение будет таким же, как и количество запросов в очереди.

Вот мой обработчик сбоя запроса,Я добавляю повторную попытку при неудачной загрузке файла.Но я не хочу, чтобы при отмене запроса был запущен механизм повторных попыток, поэтому я установил userInfo (ignore: true) для запроса объекта, чтобы предотвратить его выполнение.

- (void) downloadDidFailed:(ASIHTTPRequest *)req
{
    NSLog(@"request failed");
    NSLog(@"%d", self.queue.requestsCount);

    if(![self.queue showAccurateProgress])
    {
        [self.queue setTotalBytesToDownload:[self.queue totalBytesToDownload]-1];
        NSLog(@"totalBytesToDownload=%lld", self.queue.totalBytesToDownload);
    }

    NSDictionary * userInfo = req.userInfo;
    if([[userInfo valueForKey:@"ignore"] boolValue]) return; // ignore retry

    int retryTimes = [[req.userInfo objectForKey:@"retryTimes"] intValue];
    if(retryTimes<kMU_MaxRetry)
    {
        ++ retryTimes;
        NSLog(@"retry %d", retryTimes);
        ASIHTTPRequest * newReq = [ASIHTTPRequest requestWithURL:req.url];
        [newReq setDownloadDestinationPath:req.downloadDestinationPath];
        [newReq setTemporaryFileDownloadPath:req.temporaryFileDownloadPath];
        newReq.userInfo = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"%d", retryTimes] forKey:@"retryTimes"];
        [self.queue addOperation:newReq];

        NSLog(@"%d", self.queue.requestsCount);
    }else{  // reach max retry, fail it
        [self.failures addObject:req];
    }
}

Я не уверен, чтоесть лучшее решение, надеюсь, оно поможет вам.

...