私はしばらくの間立ち往生しており、助けが必要です。 AFNetworking 2.0にはAFHTTPRequestOperation
があるので、NSOperationQueue
を簡単に使用でき、いくつかの依存関係があります。したがって、ここにあるのはAFHTTPSessionManager
とNSURLSession
だけで、サブクラスNSOperation
はありません。 APIClient
をサブクラス化するクラスAFHTTPSessionManager
があります。私はそのクラスを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
としてラップする方法で実装する方法はありますか?だから私がやりたいこと-私は2つのネットワーク呼び出しを並行して実行できるようにしたいと思っています。その後、最初の2つの呼び出しの2番目のネットワーク呼び出しに依存する別のメソッド呼び出しを行います。何が最善のアプローチとなるか考えていますか?
非同期のAFHTTPSessionManager
サブクラスでNSOperation
リクエストをラップするクラスの小さなセット( https://github.com/robertmryan/AFHTTPSessionOperation/ )を書きました。その後、それを使用してmaxConcurrentOperation
制約、または操作の依存関係を楽しむことができます。
たとえば、次の例では、2つの同時要求を発行し、これらの両方の要求の完了に応じて完了操作を行います。
// 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
2つのリクエストしか処理しないので、ディスパッチグループを使用して同じことを実行することもできます。
// 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
を呼び出すように注意する必要があります。