我已经搜索了很多关于如何同步运行AFNetworking 2.0的示例和教程,并且只找到了AFNetworking 1.0的解决方案。我找到了什么:Can AFNetworking return data synchronously (inside a block)?
我的例子:
- (User *)getUserWithUsername: (NSString *) username andPassword: (NSString *) password {
NSDictionary *params = @{@"email": username, @"password": password};
[[DCAPIClient sharedClient] POST:@"login" parameters:params success:^(NSURLSessionDataTask * __unused task, id JSONResult) {
NSLog(@"JSON %@", JSONResult);
BOOL errorCode = [JSONResult objectForKey:@"error"];
if (!errorCode) {
self.username = [JSONResult objectForKey:@"name"];
// Fill the attributes
// self.email = .. a
} else {
// error with login show alert
}
} failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
NSLog(@"error %@", error);
}];
// this does not work
//[[[DCAPIClient sharedClient] operationQueue] waitUntilAllOperationsAreFinished];
if (self.username == nil) {
return nil;
}
return self;
}
但这不起作用,因为首先调用if (self.username == nil)
。
如何让AFNetworking 2.0 lib同步运行,我可以返回响应?
DCAPIClient:AFHTTPSessionManager
+ (instancetype)sharedClient {
static DCAPIClient *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedClient = [[DCAPIClient alloc] initWithBaseURL:[NSURL URLWithString:DCAPIBaseURLString]];
_sharedClient.responseSerializer = [AFJSONResponseSerializer serializer];
});
return _sharedClient;
}
答案 0 :(得分:5)
仇恨者会讨厌,但有时你只是希望你的HTTP调用是同步的。
为此,您可以使用AFNetworking-Synchronous库。它为AFHTTPRequestOperationManager
添加了一个方便的类别,其中包含syncGET
和syncPOST
等同步方法,这些方法在内部使用AFNetworking的waitUntilFinished
来实现同步调用。
答案 1 :(得分:0)
我不确定你为什么这样做,但一个解决方案是使用回调块。像这样:
- (void)getUserWithUsername: (NSString *) username andPassword: (NSString *) password success:(void (^)(User *user))success failure:(void (^)(NSError *error))failure
{
NSDictionary *params = @{@"email": username, @"password": password};
__weak __typeof(self)weakSelf = self;
[[DCAPIClient sharedClient] POST:@"login" parameters:params success:^(NSURLSessionDataTask * __unused task, id JSONResult) {
BOOL errorCode = [JSONResult objectForKey:@"error"];
if (!errorCode) {
weakSelf.username = [JSONResult objectForKey:@"name"];
if (weakSelf.username == nil) {
failure(nil);
}else{
success(weakSelf)
}
} else {
failure(nil);
}
} failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
failure(error);
}];
}
答案 2 :(得分:0)
您不应该使本机异步方法同步,而是使您的调用站点异步。
也就是说,您的方法变为异步并提供完成处理程序:
- (void) userWithUsername:(NSString *)username
password:(NSString *)password
completion:(completion_handler_t)completion;
其中completion_handler_t
是一个类型定义,可以像这样在头文件中声明:
typedef void (^completion_handler_t)(User*, NSError*);
请注意,使用typedef
是可选的,可能会使您的代码更易于理解。
然后您可以按如下方式使用它:
[self userWithUsername:username
password:password
completion:^(User* user, NSError*error){
// Check error; do something with user
...
}];
您可以按如下所示实现它:
- (void) userWithUsername:(NSString *)username
password:(NSString *)password
completion:(completion_handler_t)completion
{
NSDictionary *params = @{@"email": username, @"password": password};
[[DCAPIClient sharedClient] POST:@"login" parameters:params
success:^(NSURLSessionDataTask * __unused task, id JSONResult) {
NSLog(@"JSON %@", JSONResult);
BOOL errorCode = [JSONResult objectForKey:@"error"];
if (!errorCode) {
self.username = [JSONResult objectForKey:@"name"];
// Fill the attributes
// self.email = .. a
if (completion) {
completion(theUser, nil); // completion(self, nil)??
}
} else {
if (completion) {
completion(nil, error);
}
}
} failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
if (completion) {
completion(nil, error);
}
}];
}