使用NSOperation AFNetworking 3.0 AFHTTPSessionManager

时间:2016-01-12 21:07:29

标签: ios objective-c afnetworking nsurlsession

我现在被困住了一段时间,我需要帮助。所以在AFNetworking 2.0中我们有AFHTTPRequestOperation所以我可以轻松使用NSOperationQueue并拥有一些依赖关系。所以我们现在只有AFHTTPSessionManagerNSURLSession不是NSOperation的子类。我的类APIClientAFHTTPSessionManager的子类。我将该类用作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?所以我想做什么 - 我希望能够并行运行两个网络呼叫,然后再进行另一个方法调用,这取决于前两个呼叫的第二次网络呼叫。你知道什么是最好的方法吗?

1 个答案:

答案 0 :(得分:33)

我编写了一组快速的一组类(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

使用调度组,您只需要注意successfailure块中的每个路径都会调用dispatch_group_leave