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

AFNetworking 3.0 AFHTTPSessionManager с использованием NSOperation

Я застрял сейчас некоторое время, и мне нужна помощь. Поэтому в AFNetworking 2.0 мы имеем AFHTTPRequestOperation, поэтому я мог бы легко использовать NSOperationQueue и иметь некоторые зависимости. Итак, теперь у нас есть только AFHTTPSessionManager и NSURLSession, которые не подклассы NSOperation. У меня есть класс APIClient, который подклассы AFHTTPSessionManager. Я использую этот класс как singleton как sharedClient. Я переопределил GET и POST, поэтому, например, GET выглядит так:

- (NSURLSessionDataTask *)GET:(NSString *)URLString
               parameters:(NSDictionary *)parameters
                  success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                  failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure {
NSURLSessionDataTask *task = [super GET:URLString parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) {
    success(task, responseObject);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
    failure(task, [Response createErrorWithAFNetworkingError:error]);
}];

return task;
}

Есть ли у вас какие-либо идеи о том, как реализовать таким образом (если возможно) обернуть это как NSOperation? Так что я хочу сделать - я хочу иметь возможность запускать параллельно два сетевых вызова, а после этого есть другой вызов метода, который зависит от второго сетевого вызова первых двух вызовов. Есть ли у вас какие-либо идеи, что лучше всего подходит?

4b9b3361

Ответ 1

Я написал небольшой набор классов (https://github.com/robertmryan/AFHTTPSessionOperation/), которые завершают запросы AFHTTPSessionManager в асинхронном подклассе NSOperation. Затем вы можете использовать это для использования ограничений maxConcurrentOperation или зависимостей операций.

Например, здесь пример, в котором мы выдаем два одновременных запроса и выполняем операцию завершения, зависящую от завершения обоих этих запросов:

//  ViewController.m

#import "ViewController.h"
#import "AFNetworking.h"
#import "AFHTTPSessionOperation.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    NSString *urlString1 = @"...";
    NSString *urlString2 = @"...";

    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.name = @"AFHTTPSessionManager queue";

    NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"All done");
    }];

    NSOperation *op1 = [AFHTTPSessionOperation operationWithManager:manager HTTPMethod:@"GET" URLString:urlString1 parameters:nil uploadProgress:nil downloadProgress:nil success:^(NSURLSessionDataTask *task, id responseObject) {
        NSLog(@"finished 1");
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSLog(@"failed 1 - error = %@", error.localizedDescription);
    }];
    [completionOperation addDependency:op1];

    NSOperation *op2 = [AFHTTPSessionOperation operationWithManager:manager HTTPMethod:@"GET" URLString:urlString2 parameters:nil uploadProgress:nil downloadProgress:nil success:^(NSURLSessionDataTask *task, id responseObject) {
        NSLog(@"finished 2");
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
        NSLog(@"failed 2 - error = %@", error.localizedDescription);
    }];
    [completionOperation addDependency:op2];

    [queue addOperations:@[op1, op2] waitUntilFinished:false];
    [[NSOperationQueue mainQueue] addOperation:completionOperation];  // do this on whatever queue you want, but often you're updating UI or model objects, in which case you'd use the main queue
}

@end

Следует отметить, что, поскольку вы имеете дело только с двумя запросами, вы также можете использовать группы отправки для выполнения того же:

//  ViewController.m

#import "ViewController.h"
#import "AFNetworking.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    NSString *urlString1 = @"...";
    NSString *urlString2 = @"...";

    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    dispatch_group_t group = dispatch_group_create();

    dispatch_group_enter(group);
    [manager GET:urlString1 parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"finished 1");
        dispatch_group_leave(group);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"failed 1 - error = %@", error.localizedDescription);
        dispatch_group_leave(group);
    }];

    dispatch_group_enter(group);
    [manager GET:urlString2 parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"finished 2");
        dispatch_group_leave(group);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"failed 2 - error = %@", error.localizedDescription);
        dispatch_group_leave(group);
    }];

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"All done");
    });
}

@end

С группами отправки вам просто нужно быть осторожным, чтобы каждый путь в обоих success и failure блокировал вызов dispatch_group_leave.