AFHTTPSessionManager和NSOperation队列具有依赖关系(AFNetworking 2)

时间:2013-10-16 14:56:19

标签: ios objective-c afnetworking-2

在AFNetworking的早期版本中,我可以使用AFHTTPRequestOperation创建多个请求,在它们之间创建依赖关系并轻松地将它们排入队列。示例(在AFHTTPClient子类内部):

NSURLRequest *categoriesRequest = [self requestWithMethod:@"GET" path:@"categories" parameters:nil];
AFHTTPRequestOperation *categoriesOperation = [self HTTPRequestOperationWithRequest:categoriesRequest success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSArray *jsonCategories = responseObject;
    for (NSDictionary *jsonCategory in jsonCategories) {
        SPOCategory *category = [[SPOCategory alloc] initWithDictionary:jsonCategory];
        [self.categories addObject:category];
    }
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    // …
}];

NSURLRequest *incidencesRequest = [self requestWithMethod:@"GET" path:@"incidences" parameters:nil];
AFHTTPRequestOperation *incidencesOperation = [self HTTPRequestOperationWithRequest:incidencesRequest success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSArray *jsonIncidences = responseObject;
    for (NSDictionary *jsonIncidence in jsonIncidences) {
        SPOIncidence *incidence = [[SPOIncidence alloc] initWithDictionary:jsonIncidence];
        [self.incidences addObject:incidence];
    }

    completionBlock(self.incidences, self.categories, nil);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    // …
}];

[incidencesOperation addDependency:categoriesOperation];

[self enqueueBatchOfHTTPRequestOperations:@[categoriesOperation, incidencesOperation] progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
    // Processing…
} completionBlock:^(NSArray *operations) {
    // Completed
}];

我知道我可以继续使用AFHTTPRequestOperation但是,我想知道是否有类似的方法在AFHTTPSessionManager的子类中实现同样的事情,使用{{1}作为支持库而不是NSURLSession

谢谢!

1 个答案:

答案 0 :(得分:2)

AFHTTPSessionManager的连接工厂方法创建将由NSURLSessionDataTask对象表示的连接。

AFHTTPRequestOperation不同,这些不是NSOperation子类,因此无法声明依赖关系。

可以设想包装像

这样的工厂方法
- (NSURLSessionDataTask *)GET:(NSString *)URLString
                   parameters:(NSDictionary *)parameters
                      success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                      failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure;

进入一个返回NSOperation对象的辅助方法/函数。但这可能(将)变得麻烦,看起来很奇怪。

如果您有足够的勇气考虑另一个第三方库,您可以解决您的问题,如下所述:

这个想法是通过“Promise”来表示异步操作的最终结果。将Promise视为结果的占位符,最终将由操作设置。所以,基本上你将一个工厂方法包装成一个,然后有效地产生一个具有这个签名的方法:

-(Promise*) fetchCategories;

-(Promise*) fetchCategoriesWithParameters:(NSDictionary*)parameters;

请注意,上述方法是异步 - 但它们没有完成处理程序。承诺将提供此设施。

最初,当fetchCategories返回时,promise对象不会“包含”结果。

分别通过“注册”完成处理程序块 错误处理程序块分别得到(稍后)最终结果和错误>具有then属性,如此(伪代码):

  [self.fetchCategoriesWithParameters].then( 
      <success handler block>, 
      <failure handler block> ); 

更完整的代码段:

Promise* categoriesPromise = [self fetchCategories];

categoriesPromise.then(^id(id result){
    self.categories = result;
    ... // (e.g, dispatch on main thread and reload table view)
    return nil;
}, ^id(NSError* error){
    NSLog(@"Error: %@", error);
    return nil;
});

注意:成功处理程序块的参数 result 是操作的最终结果,即 responseObject

现在,为了“链接”多个异步操作(包括处理程序),您可以这样做:

self.categoriesPromise = [self fetchCategories];

Promise* finalResult = self.categoriesPromise.then(^id(id result){
    NSArray *jsonCategories = result;
    for (NSDictionary *jsonCategory in jsonCategories) {
        SPOCategory *category = [[SPOCategory alloc] initWithDictionary:jsonCategory];
        [self.categories addObject:category];
    }
   return [self fetchIncidencesWithParams:result);
}, nil)
.then(^id(id result){
    NSArray *jsonIncidences = result;
    for (NSDictionary *jsonIncidence in jsonIncidences) {
        SPOIncidence *incidence = 
          [[SPOIncidence alloc] initWithDictionary:jsonIncidence];
        [self.incidences addObject:incidence];
    }
    return @[self.incidences, self.categories];
}, nil)
.then(^id(id result){
    NSArray* incidences = result[0];
    NSArray* categories = result[1];
    ...
    return nil;
}, nil /* error handler block */);

您创建并“解析”(即设置结果)Promise,如下所示:

- (Promise*) fetchCategories {
    Promise* promise = [[Promise alloc] init];

    NSURLRequest *categoriesRequest = [self requestWithMethod:@"GET" path:@"categories" parameters:nil];
    AFHTTPRequestOperation *categoriesOperation = [self  HTTPRequestOperationWithRequest:categoriesRequest success:^(AFHTTPRequestOperation *operation, id responseObject) {
        [promise fulfillWithResult:responseObject];
    }
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        [promise rejectWithReason:error];
    }];

    return promise;
}

声明:

有一些第三方Objective-C库以这种或类似的方式实现Promise。我是RXPromise的作者,它根据Promises/A+规范实现了一个承诺。