Tra*_*ggs 8 objective-c ios afnetworking-2
我知道还有另外一个类似的问题,但它适用于较旧版本的AFNetworking,并且无论如何都没有真正回答它.
我有以下代码:
AFHTTPRequestOperationManager* manager = [AFHTTPRequestOperationManager manager];
manager.securityPolicy.allowInvalidCertificates = YES;
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setAuthorizationHeaderFieldWithUsername: currentUser() password: currentPassword()];
__block NSDictionary* response = nil;
AFHTTPRequestOperation* operation = [manager
GET: @"https://10.20.30.40:8765/foobar"
parameters: [NSDictionary dictionary]
success:^(AFHTTPRequestOperation* operation, id responseObject){
response = responseObject;
NSLog(@"response (block): %@", response);
}
failure:^(AFHTTPRequestOperation* operation, NSError* error){
NSLog(@"Error: %@", error);}
];
[operation waitUntilFinished];
NSLog(@"response: %@", response);
...
Run Code Online (Sandbox Code Playgroud)
如果我运行它,我将在日志中看到的是:
2013-12-09 09:26:20.105 myValve[409:60b] response: (null)
2013-12-09 09:26:20.202 myValve[409:60b] response (block): {
F00005 = "";
F00008 = "";
F00013 = "";
}
Run Code Online (Sandbox Code Playgroud)
本NSLog
是后的waitUntilFinished
火灾第一.我预计它会第二次开火.我错过了什么?
Rob*_*Rob 32
几点想法:
问题是waitUntilFinished
等待核心网络操作完成,但不会等待success
或failure
完成块.如果要等待完成块,可以使用信号量:
__block NSDictionary* response = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
manager.completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
AFHTTPRequestOperation* operation = [manager GET: @"https://10.20.30.40:8765/foobar"
parameters: [NSDictionary dictionary]
success:^(AFHTTPRequestOperation* operation, id responseObject){
response = responseObject;
NSLog(@"response (block): %@", response);
dispatch_semaphore_signal(semaphore);
}
failure:^(AFHTTPRequestOperation* operation, NSError* error){
NSLog(@"Error: %@", error);
dispatch_semaphore_signal(semaphore);
}];
NSLog(@"waiting");
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// [operation waitUntilFinished];
NSLog(@"response: %@", response);
Run Code Online (Sandbox Code Playgroud)
或者,您可以将它包装在您自己的并发NSOperation
子类中,isFinished
在AFHTTPRequestOperation
完成块中发布,从而消除semaphore
过程中的内容.
注意,请确保指定completionQueue
是否在主队列上执行信号量,因为如果没有,则AFNetworking默认将完成处理程序分派到主队列,并且您可以死锁.
顺便说一句,你永远不应该阻止主队列(可怜的用户体验,你的应用程序可能被监视程序进程杀死等等),所以如果你是从主队列中执行此操作,我不鼓励使用其中任何一个waitUntilFinished
或者信号.最好只在完成块中启动您需要的任何内容,让主队列在此异步网络操作正在进行时继续执行,例如:
[activityIndicatorView startAnimating];
AFHTTPRequestOperation* operation = [manager GET: @"https://10.20.30.40:8765/foobar"
parameters: [NSDictionary dictionary]
success:^(AFHTTPRequestOperation* operation, id responseObject){
// do whatever you want with `responseObject` here
// now update the UI, e.g.:
[activityIndicatorView stopAnimating];
[self.tableView reloadData];
}
failure:^(AFHTTPRequestOperation* operation, NSError* error){
// put your error handling here
// now update the UI, e.g.:
[activityIndicatorView stopAnimating];
}];
// NSLog(@"waiting");
// dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// // [operation waitUntilFinished];
// NSLog(@"response: %@", response);
Run Code Online (Sandbox Code Playgroud)听起来您希望让模型让UI在模型对象完成更新时进行任何必要的更新.因此,您可以使用自己的块参数,以便视图控制器可以告诉模型对象完成后要做什么(而不是使用waitUntilFinished
或信号量使网络操作阻塞主队列).例如,假设您的模型有一些这样的方法:
- (void)updateModelWithSuccess:(void (^)(void))success failure:(void (^)(NSError *error))failure
{
AFHTTPRequestOperationManager* manager = [AFHTTPRequestOperationManager manager];
manager.securityPolicy.allowInvalidCertificates = YES;
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setAuthorizationHeaderFieldWithUsername: currentUser() password: currentPassword()];
AFHTTPRequestOperation* operation = [manager GET: @"https://10.20.30.40:8765/foobar"
parameters: [NSDictionary dictionary]
success:^(AFHTTPRequestOperation* operation, id responseObject){
// do your model update here
// then call the success block passed to this method (if any),
// for example to update the UI
if (success)
success();
}
failure:^(AFHTTPRequestOperation* operation, NSError* error){
NSLog(@"Error: %@", error);
// if caller provided a failure block, call that
if (failure)
failure(error);
}];
}
Run Code Online (Sandbox Code Playgroud)
然后您的视图控制器可以执行以下操作:
[modelObject updateModelWithSuccess:^{
// specify UI updates to perform upon success, e.g.
// stop activity indicator view, reload table, etc.
} failure:^(NSError *error){
// specify any UI updates to perform upon failure
}]
Run Code Online (Sandbox Code Playgroud)
最后,您的代码可以使用AFNetworking使用的相同样式的完成块.如果您希望模型返回信息,您可以将其他参数添加到完成块本身,但我认为上面说明了基本概念.
归档时间: |
|
查看次数: |
7241 次 |
最近记录: |