2013-03-01 3 views
4

У меня есть приложение iOS, сделанное с AFNetworking. У меня есть отдельный пользовательский подкласс httpclient, и я использую его для использования api и загрузки двоичных файлов с сервера.AFNetworking. Результат загрузки для всех операционных очередей

Мне нужно загрузить около 100 файлов. Безопасно ли перебирать массив url и создавать одно AFHTTPRequestionOperation для каждого URL-адреса? Мой код:

NSMutableURLRequest* rq = [[MIHTTPClient sharedInstance] requestWithMethod:@"GET" path:@"...." parameters:nil]; 
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:rq] ; 
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO]; 

[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 
    //completion 

} failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
    //manage error 
}]; 


[[MIHTTPClient sharedInstance] enqueueHTTPRequestOperation:operation]; 

Как я могу получить обратную связь из этой очереди? Я не вижу никакого протокола HTTPClientDelegate или что-то вроде этого.

благодаря

ответ

5

Что касается прогресса см setDownloadProgressBlock (часть AFURLConnectionOperation, из которого AFHTTPRequestOperation является подклассы), например:

[operation setDownloadProgressBlock:^(NSInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite) { 
    NSLog(@"Sent %d of %d bytes, %@", totalBytesWritten, totalBytesExpectedToWrite, path); 
}]; 

И, в вашем примере кода, вы звоните setCompletionBlockWithSuccess:failure:, так что предоставляет статус завершения отдельных операций. Лично в моем небольшом тесте, я просто сохранить массив моих запрашиваемых загрузок, и эти три блока (прогресс, успех и неудача) обновить код состояния моей загрузки, как так:

for (NSInteger i = 0; i < 20; i++) 
{ 
    NSURLRequest *request = ... // set the request accordingly 

    // create a download object to keep track of the status of my download 

    DownloadObject *object = [[DownloadObject alloc] init]; 
    download.title = [NSString stringWithFormat:@"Download %d", i]; 
    download.status = kDownloadObjectStatusNotStarted; 
    [self.downloadObjects addObject:download]; 

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; 

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 
     download.status = kDownloadObjectStatusDoneSucceeded; 

     // update my UI, for example, I have table view with one row per download 
     // 
     // [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:i inSection:0]] 
     //      withRowAnimation:UITableViewRowAnimationNone]; 
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
     download.status = kDownloadObjectStatusDoneFailed; 

     // update UI 
     // 
     // [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:i inSection:0]] 
     //      withRowAnimation:UITableViewRowAnimationNone]; 
    }]; 

    [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { 
     download.totalBytesRead = totalBytesRead; 
     download.status = kDownloadObjectStatusInProgress; 

     // update UI 
     // 
     // [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:i inSection:0]] 
     //      withRowAnimation:UITableViewRowAnimationNone]; 
    }]; 

    [queue addOperation:operation]; 
} 

Вы можете сохранить отслеживать отдельные загрузки таким образом. Вы также можете просто отслеживать незавершенные операции (или запросить свойство объекта operationQueue и посмотреть на его свойство operationCount).


С точки зрения загрузки 100 файлов, два соображения:

  • Я бы подумал, что вы хотите позвонить setMaxConcurrentOperationCount на operationQueue вашего HTTPClient подкласса, установив его в какой-то разумное количество (4 или 5), глядя на код AFNetworking, похоже, что это не так. Я нахожу, что уменьшаются отдачи, если вы намного выше этого, и если все файлы находятся на одном сервере, существуют ограничения на то, сколько одновременных операций может быть выполнено между данным клиентом и данным сервером.

  • Я читал анекдотические утверждения о том, что Apple отклонит приложения, которые делают необычные запросы по сотовой сети. См. https://stackoverflow.com/a/14922807/1271826.

+0

setDowloadProgressBlock полезен для одного соединения, и я его использую. Я ищу ту же функцию для всей очереди. Спасибо за setMaxConcurrentOperationCount ... код AFN задал это значение в NSOperationQueueDefaultMaxConcurrentOperationCount (-1) – IgnazioC

+1

@IgnazioC Да, я увидел, где они устанавливают 'maxConcurrentOperationCount', именно поэтому я указываю, что для вас важно сбросить его на что-то например, 4 или 5, если вы собираетесь делать 100 загрузок. Если вы этого не сделаете, одновременно будет запущено все 100 операций, а вторые - в конечном итоге. Установка 'maxConcurrentOperationCount' решит эту проблему. Всегда важно при большом количестве загрузок. – Rob

+0

Выполнение «всей очереди», между блоком прогресса загрузки операции и двумя блоками завершения операции, у вас есть все, что вам нужно. Вы можете отслеживать количество ожидающих загрузки или, как в моем обновленном ответе, отслеживать состояние отдельных загрузок в отдельном массиве.Хотя я могу понять, что вам может понадобиться блок для статуса всей очереди, который избыточен с учетом этих трех других блоков. – Rob

Смежные вопросы