AFNetworking可以同步返回数据(在块内)吗?

Sha*_*ali 46 synchronous ios objective-c-blocks afnetworking

我有一个使用AFJSONRequestOperation的函数,我希望仅在成功后返回结果.你能指出我正确的方向吗?对于块和AFNetworking,我仍然有点无能为力.

-(id)someFunction{
    __block id data;

    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
        success:^(NSURLRequest *request, NSHTTPURLResponse *response, id json){
            data = json;
            return data; // won't work
        }
        failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error){

        }];



    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation: operation];

    return data; // will return nil since the block doesn't "lock" the app.
}
Run Code Online (Sandbox Code Playgroud)

mat*_*ttt 56

要阻止主线程的执行直到操作完成,您可以[operation waitUntilFinished]在将其添加到操作队列后执行.在这种情况下,你不需要return在块中; 设置__block变量就足够了.

也就是说,我强烈反对强制异步操作​​同步方法.有时候让你头脑发热是很棘手的,但如果有任何方法你可以将它构造成异步,那几乎肯定是要走的路.

  • 我怀疑`waitUntilFinished`技巧对某些人不起作用,因为在操作完成后,在主队列上使用`dispatch_async`执行成功和失败块(默认情况下).如果你没有在runloop中执行,例如单元测试,那么程序可能会提前退出,而不会让GCD有机会运行回调. (9认同)
  • 不幸的是,waitUntilFinished技巧对我不起作用.我有几种本质上是同步的业务方法.令人遗憾的是,AFNetworking完全忽略了这种用例. (7认同)
  • `[operation waitUntilFinished];`对我来说也不起作用. (5认同)
  • 我认为理想情况下,任何网络SDK都应该允许用户选择是否需要异步操作; 它不应该强制特定的模型,尽管它可能暗示一个. (4认同)

Kas*_*sik 12

我正在使用信号量来解决这个问题.这段代码是在我自己继承的类中实现的AFHTTPClient.

__block id result = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSURLRequest *req = [self requestWithMethod:@"GET"
                                       path:@"someURL"
                                 parameters:nil];
AFHTTPRequestOperation *reqOp = [self HTTPRequestOperationWithRequest:req
                                                              success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                                                  result = responseObject;                                                                          
                                                                  dispatch_semaphore_signal(semaphore);
                                                              }
                                                              failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                                                  dispatch_semaphore_signal(semaphore);
                                                              }];
reqOp.failureCallbackQueue = queue;
reqOp.successCallbackQueue = queue;
[self enqueueHTTPRequestOperation:reqOp];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_release(semaphore);
return result;
Run Code Online (Sandbox Code Playgroud)


Ikh*_*aat 11

我建议您不要使用AFNetworking(或一般的块)制作同步方法.一个好的方法是创建另一个方法并使用成功块中的json数据作为参数.

- (void)methodUsingJsonFromSuccessBlock:(id)json {
    // use the json
    NSLog(@"json from the block : %@", json); 
}

- (void)someFunction {
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
        success:^(NSURLRequest *request, NSHTTPURLResponse *response, id json){
            // use the json not as return data, but pass it along to another method as an argument
            [self methodUsingJsonFromSuccessBlock:json];
        }
        failure:nil];

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation: operation];
}
Run Code Online (Sandbox Code Playgroud)


joe*_*ick 6

值得注意的是,AFNetworking的AFClient的某些功能仍然可以以同步方式使用,这意味着您仍然可以使用诸如授权标头和分段上传等细节.

例如:

NSURLRequest *request = [self.client requestWithMethod: @"GET"
                                                  path: @"endpoint"
                                            parameters: @{}];
NSHTTPURLResponse *response = nil;
NSError *error = nil;

NSData *responseData = [NSURLConnection sendSynchronousRequest: request
                                             returningResponse: &response
                                                         error: &error];
Run Code Online (Sandbox Code Playgroud)

请记住检查response.statusCode这种情况,因为此方法不会将HTTP失败代码视为错误.