在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
。
谢谢!
答案 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+规范实现了一个承诺。