AFNetworking 未在块内同步返回数据

Posted

技术标签:

【中文标题】AFNetworking 未在块内同步返回数据【英文标题】:AFNetworking not returning data synchronously inside a block 【发布时间】:2012-08-29 21:03:21 【问题描述】:

无法使用 AFNetworking 在块内同步接收 JSON。我检查了这个solution。它 在方法结束时总是 nil。

这是我的方法:

- (BOOL)whois:(NSString *)domain withZone: (NSString*) zone
        
    __block NSString *resultCode;

    NSURL *url = [[NSURL alloc] initWithString:@"myurl"];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];

    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)      
        resultCode = [JSON valueForKeyPath:[NSString stringWithFormat:@"%@.%@", domain,zone]];  //checked with NSLog, works well              
     failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) 
        NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo);
    ];

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

    if(resultCode == @"available") //nil here
    
        return YES;
    
    return NO; 

【问题讨论】:

【参考方案1】:

不要创建NSOperationQueue,而是使用[operation start] 启动AFJSONRequestOperation,然后调用[operation waitUntilFinished],它会阻塞主线程直到它完成。那么你的 resultCode 不应该是 nil。

正如 @mattt 在您链接的帖子中所说,强烈建议不要像这样冻结线程。考虑找出另一种方法来执行此操作,例如从成功块调用您希望继续的新方法,以及从失败块调用不同的失败方法。

【讨论】:

【参考方案2】:

您的方法无法在当前设计下运行。

- (BOOL)whois:(NSString *)domain withZone: (NSString*) zone
        
    __block NSString *resultCode;

    NSURL *url = [[NSURL alloc] initWithString:@"myurl"];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];

    // *** Runs 1st
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)      

        // *** runs 3rd
        resultCode = [JSON valueForKeyPath:[NSString stringWithFormat:@"%@.%@", domain,zone]];  //checked with NSLog, works well              
     failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) 
        NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo);
    ];

    // *** Runs 2nd
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation: operation];
    [operation waitUntilFinished];

    if(resultCode == @"available") //nil here
    
        return YES;
    
    return NO; 

由于块中的材料是第三次异步运行,因此您将无法以当前设计的方式将该值返回给更大的方法。也许使用这样的东西:

- (void)whois:(NSString *)domain withZone: (NSString*) zone
        

    NSURL *url = [[NSURL alloc] initWithString:@"myurl"];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];

    __weak id weakSelf = self;
    // Runs 1st
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)      

        NSString *resultCode = [JSON valueForKeyPath:[NSString stringWithFormat:@"%@.%@", domain,zone]];  //checked with NSLog, works well       
        [weakSelf receivedResultCode:resultCode];       
     failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) 
        NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo);
    ];


- (void) receivedResultCode:(NSString *)resultCode 
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation: operation];
    [operation waitUntilFinished];

    if(resultCode == @"available") //nil here
    
        // do @YES stuff
    
    else 
        // do @NO stuff
    

显然,您必须更改调用它的人的设计,因为它不会以您指定的方式返回值。也许有更好的解决方案,但我认为这是它工作所需的设计类型。

【讨论】:

以上是关于AFNetworking 未在块内同步返回数据的主要内容,如果未能解决你的问题,请参考以下文章

块内函数的返回值

AFNetwork、Magical Record和块内保存

如何在块内制作边框底部? [关闭]

为啥在块外设置时,`scheduledTimer` 会正确触发,而不是在块内?

为啥实例变量在块内时似乎消失了?

Oracle在块内是如何组织和管理数据的