- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我知道有 another similar question ,但它适用于旧版本的 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);
...
如果我运行它,我将在我的日志中看到的是:
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 = "";
}
在waitUntilFinished
之后 的NSLog
首先触发。我预计它会第二次开火。我错过了什么?
最佳答案
几个想法:
问题是waitUntilFinished
将等待核心网络操作完成,但不会等待成功
或失败
完成 block 。如果你想等待完成 block ,你可以使用信号量:
__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);
或者,您可以将其包装在您自己的并发 NSOperation
子类中,在 AFHTTPRequestOperation
完成 block 中发布 isFinished
,消除 进程中的信号量
。
注意,如果在主队列上执行信号量,请确保指定 completionQueue
因为,在没有它的情况下,AFNetworking 默认将完成处理程序分派(dispatch)到主队列,您可能会死锁。
顺便说一句,你永远不应该阻塞主队列(糟糕的用户体验,你的应用程序可能会被看门狗进程杀死,等等),所以如果你从主队列这样做,我会劝阻waitUntilFinished
或信号量的使用。最好从完成 block 中启动任何你需要的东西,让主队列在这个异步网络操作正在进行时继续执行,例如:
[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);
听起来您想让您的模型让 UI 在模型对象完成更新后进行任何必要的更新。因此,您可以使用自己的 block 参数,以便 View Controller 可以告诉模型对象在完成时做什么(而不是使用 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);
}];
}
然后你的 View Controller 可以做类似的事情:
[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
}]
最重要的是,您的代码可以使用 AFNetworking 使用的相同样式的完成 block 。如果您希望模型将信息传回,您可以向完成 block 本身添加额外的参数,但我认为以上说明了基本思想。
关于ios - AFNetworking-2 waitUntilFinished 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20476957/
我正在制作一个使用 AFNetworking 库的项目。我用它来检查网络服务的登录名和密码。如果没问题,这会给我一个 200 代码。如果是 200,我将一个 bool 值设置为 true,以便应用程序
您好,我正在使用 Swift 构建应用程序。我需要按特定顺序处理通知。因此,我正在尝试使用 addOperations waitUntilFinished。 这是我做的: let oldify = N
我知道有 another similar question ,但它适用于旧版本的 AFNetworking,并且无论如何都没有真正回答它。 我有以下代码: AFHTTPRequestOperation
addOperation:waitUntilFinished 是否仅适用于 iOS 4.3 及更高版本?为什么我会收到此警告,我是不是错过了什么? 即使我收到这条警告消息,我的应用程序仍然可以正常运行
我有 NSOperation 和 AFHTTPClient 请求。在操作结束时,我需要对请求执行另外 N 个操作,并等待请求完成以将主要操作标记为已完成 @interface MyOperation
我是一名优秀的程序员,十分优秀!