我正在使用AFNetworking发出JSON请求,然后调用[operation waitUntilFinished]来等待操作和成功或失败阻止。但是,它看起来似乎正确 - 在日志消息方面,我得到“0”,“3”,“1”而不是“0”,“1”,“3”
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://google.com"]];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
httpClient.parameterEncoding = AFFormURLParameterEncoding;
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:@"query", @"q", nil];
NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET" path:[url path] parameters:params];
NSLog(@"0");
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *innerRequest, NSHTTPURLResponse *response, id JSON) {
NSLog(@"1");
gotResponse = YES;
} failure:^(NSURLRequest *innerRequest, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(@"2");
gotResponse = YES;
}];
NSLog(@"Starting request");
[operation start];
[operation waitUntilFinished];
NSLog(@"3");
答案 0 :(得分:14)
这可以通过使用AFNetworking来设置请求,但进行同步调用然后手动处理完成块。非常简单。 AFNetworking似乎不支持这个https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-FAQ,尽管解决方法很简单。
#import "SimpleClient.h"
#import "AFHTTPClient.h"
#import "AFJSONRequestOperation.h"
#import "AFJSONUtilities.h"
@implementation SimpleClient
+ (void) makeRequestTo:(NSString *) urlStr
parameters:(NSDictionary *) params
successCallback:(void (^)(id jsonResponse)) successCallback
errorCallback:(void (^)(NSError * error, NSString *errorMsg)) errorCallback {
NSURLResponse *response = nil;
NSError *error = nil;
NSURL *url = [NSURL URLWithString:urlStr];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
httpClient.parameterEncoding = AFFormURLParameterEncoding;
NSMutableURLRequest *request = [httpClient requestWithMethod:@"POST" path:[url path] parameters:params];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if(error) {
errorCallback(error, nil);
} else {
id JSON = AFJSONDecode(data, &error);
successCallback(JSON);
}
}
@end
答案 1 :(得分:0)
这应该(几乎)有效。您致电
NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET" path:[url path] parameters:params];
可能不应该将[url path]
传递给path:
参数。在AFNetworking的土地上,该路径是基本网址之后的所有内容(例如,基本网址可能是“http://google.com”,路径是“/ gmail”或其他)。
话虽如此,使用waitUntilFinished将异步操作转换为线程阻塞同步操作可能不是一个好主意,但我确定你有理由......;)
答案 2 :(得分:0)
我遇到了同样的问题并找到了不同的解决方案。我有两个相互依赖的操作,但可以并行加载。但是,在完成第一个操作的完成块之前,不能执行第二个操作的完成块。
正如科林所指出的,制作网络请求阻止可能是一个糟糕的选择。这对我来说很重要,所以我是异步的。
这是我的解决方案:
// This is our lock
@interface SomeController () {
NSLock *_dataLock;
}
@end
@implementation
// This is just an example, you might as well trigger both operations in separate
// places if you get the locking right
// This might be called e.g. in awakeFromNib
- (void)someStartpoint {
AFJSONRequestOperation *operation1 = [AFJSONRequestOperation JSONRequestOperationWithRequest:[NSURLRequest requestWithURL:url1]
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id data) {
// We're done, we unlock so the next operation can continue its
// completion block
[_dataLock unlock];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id data) {
// The request has failed, so we need to unlock for the next try
[_dataLock unlock];
}];
AFJSONRequestOperation *operation2 = [AFJSONRequestOperation JSONRequestOperationWithRequest:[NSURLRequest requestWithURL:url2]
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id data) {
// The completion block (or at least the blocking part must be run in a
// separate thread
[NSThread detachNewThreadSelector:@selector(completionBlockOfOperation2:) toTarget:self withObject:data];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id data) {
// This second operation may fail without affecting the lock
}];
// We need to lock before both operations are started
[_dataLock lock];
// Order does not really matter here
[operation2 start];
[operation1 start];
}
- (void)completionBlockOfOperation2:(id)data {
// We wait for the first operation to finish its completion block
[_dataLock lock];
// It's done, so we can continue
// We need to unlock afterwards, so a next call to one of the operations
// wouldn't deadlock
[_dataLock unlock];
}
@end
答案 3 :(得分:0)
使用委托方法调用
将方法放在块中,当下载/上传完成时,该方法将调用自身。