Подтвердить что ты не робот

Как пакетный запрос с AFNetworking 2?

Итак, я переписываю приложение для iOS 7 с AFNetworking 2.0, и я столкнулся с проблемой отправки пакета запросов сразу и отслеживания их прогресса. В старом AFNetworking был enqueueBatchOfHTTPRequestOperations:progressBlock:completionBlock: метод на AFHTTPClient, это явно рефакторизовано, и я немного смущен тем, как вставлять несколько запросов.

Я создал подкласс AFHTTPSessionManager, и я использую методы POST:... и GET:... для связи с сервером. Но я не могу найти что-либо в коде и/или документах для того, чтобы вставлять несколько запросов одновременно, как со старым AFHTTPClient.

Единственное, что я могу найти, это недокументированный метод batchOfRequestOperations:progressBlock:completionBlock: на AFURLConnectionOperation, но это похоже на способ iOS 6 этого.

Очевидно, что я пропускаю что-то в новой концепции NSURLSession, которую я должен использовать для пакетных запросов или просмотра новой функции AFNetworking. Надеюсь, кто-то может помочь мне на правильном пути здесь!

tl; dr: Как отправить пакет запросов с моим подклассом AFHTTPSessionManager?

4b9b3361

Ответ 1

Спасибо Sendoa за ссылку на вопрос GitHub, где Мэтт объясняет, почему эта функциональность больше не работает. Существует ясная причина, почему это невозможно с новой структурой NSURLSession; Задачи просто не являются операциями, поэтому старый способ использования зависимостей или партий операций не будет работать.

Я создал это решение, используя dispatch_group, который позволяет выполнять пакетные запросы с помощью NSURLSession, вот (псевдо) код:

// Create a dispatch group
dispatch_group_t group = dispatch_group_create();

for (int i = 0; i < 10; i++) {
    // Enter the group for each request we create
    dispatch_group_enter(group);

    // Fire the request
    [self GET:@"endpoint.json"
       parameters:nil
          success:^(NSURLSessionDataTask *task, id responseObject) {
                  // Leave the group as soon as the request succeeded
                  dispatch_group_leave(group);
          }
      failure:^(NSURLSessionDataTask *task, NSError *error) {
                  // Leave the group as soon as the request failed
                  dispatch_group_leave(group);
              }];
}

// Here we wait for all the requests to finish
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    // Do whatever you need to do when all requests are finished
});

Я хочу посмотреть что-нибудь, что упростит работу и обсудит с Мэттом, если это что-то (когда реализовано красиво), которое можно объединить в AFNetworking. На мой взгляд, было бы здорово сделать что-то подобное с самой библиотекой. Но я должен проверить, когда у меня есть свободное время.

Ответ 2

Просто обновляю нить... У меня была такая же проблема, и после некоторых исследований я нашел несколько хороших решений, но я решил придерживаться этого:

Я использую проект под названием Bolts. Итак, для того же образца выше, опубликованного @Mac_Cain13, это будет:

[[BFTask taskWithResult:nil] continueWithBlock:^id(BFTask *task) {
    BFTask *task = [BFTask taskWithResult:nil];
    for (int i = 0; i < 10; i++) {
        task = [task continueWithBlock:^id(BFTask *task) {
            return [self executeEndPointAsync];
        }];
    }
    return task;
}] continueWithBlock:^id(BFTask *task) {
    // Everything was executed.
    return nil;
}];;

- (BFTask *) executeEndPointAsync {
    BFTaskCompletionSource *task = [BFTaskCompletionSource taskCompletionSource];
    [self GET:@"endpoint.json" parameters:nil
      success:^(NSURLSessionDataTask *task, id responseObject) {
        [task setResult:responseObject];
      }
      failure:^(NSURLSessionDataTask *task, NSError *error) {
        [task setError:error];
      }];
    }];
    return task.task;
}

В основном, он укладывает все задачи, ждет и разворачивается, пока не будет больше задач, и после того, как все будет завершено, будет выполнен последний блок завершения.

Другим проектом, который делает то же самое, является RXPromise, но для меня более понятный код Bolts.

Ответ 3

Для request, который может быть post или get, вы можете использовать AFNetworking 2.0 для пакетного управления, поскольку сначала вам нужно создать операцию следующим образом:

//Request 1
NSString *strURL = [NSString stringWithFormat:@"your url here"];
NSLog(@"scheduleurl : %@",strURL);
NSDictionary *dictParameters = your parameters here
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:strURL parameters:dictParameters error: nil];

AFHTTPRequestOperation *operationOne = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operationOne = [AFHTTPResponseSerializer serializer];

[operationOne setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
     //do something on completion
} 
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
     NSLog(@"%@",[error description]);
}];

//Request 2
NSString *strURL1 = [NSString stringWithFormat:@"your url here"];
NSLog(@"scheduleurl : %@",strURL);
NSDictionary *dictParameters1 = your parameters here
NSMutableURLRequest *request1 = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:strURL1 parameters:dictParameters1 error: nil];

AFHTTPRequestOperation *operationTwo = [[AFHTTPRequestOperation alloc] initWithRequest:request1];
operationTwo = [AFHTTPResponseSerializer serializer];

[operationTwo setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
     //do something on completion
} 
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
     NSLog(@"%@",[error description]);
}];

//Request more here if any

Теперь выполните пакетную операцию следующим образом:

//Batch operation
//Add all operation here 
NSArray *operations = [AFURLConnectionOperation batchOfRequestOperations:@[operationOne,operationTwo] progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations)
{
    NSLog(@"%i of %i complete",numberOfFinishedOperations,totalNumberOfOperations);
    //set progress here
    yourProgressView.progress = (float)numberOfFinishedOperations/(float)totalNumberOfOperations;

} completionBlock:^(NSArray *operations) 
{
    NSLog(@"All operations in batch complete");
}];

[[NSOperationQueue mainQueue] addOperations:operations waitUntilFinished:NO];

Ответ 4

В AFNetworking 2.0 AFHTTPClient был разделен на AFHTTPRequestOperationManager и AFHTTPSessionManager, поэтому, возможно, вы можете начать с первого, у которого есть свойство operationQueue.

Ответ 5

В настоящее время задачи NSURLSession не подходят для того же типа операций запроса шаблонов. См. Ответ от Mattt Thompson здесь относительно этой проблемы.

Прямой ответ: если вам нужны зависимости или партии, вам все равно придется использовать операции запроса.