【问题标题】:Getting data out of the NSURLResponse completion block从 NSURLResponse 完成块中获取数据
【发布时间】:2012-09-10 13:36:53
【问题描述】:

看来我还没有完全理解积木的概念……

在我的代码中,我必须从 asychronous block 中取出 JSON 数据,以便从 'outer' 方法返回。我google了一下,发现如果定义一个variable with __block,v̶i̶s̶i̶b̶i̶l̶i̶t̶y̶_mutability_ of这个变量会扩展为block

但是由于某种原因返回的 json 对象是 nil。我想知道为什么?

- (NSMutableDictionary *)executeRequestUrlString:(NSString *)urlString
{
__block NSMutableDictionary *json = nil;
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

[request setHTTPShouldHandleCookies:YES];
[request setHTTPMethod:@"GET"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-type"];

NSString *cookieString = [self.userDefaults objectForKey:SAVED_COOKIE];

[request addValue:cookieString forHTTPHeaderField:@"Cookie"];

[NSURLConnection sendAsynchronousRequest:request
                                   queue:[NSOperationQueue currentQueue]
                       completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
                       {

                           NSLog(@"dataAsString %@", [NSString stringWithUTF8String:[data bytes]]);

                           NSError *error1;
                           NSMutableDictionary * innerJson = [NSJSONSerialization
                                   JSONObjectWithData:data
                                              options:kNilOptions
                                                error:&error1];
                           json = innerJson;

                       }];

    return json;
}

【问题讨论】:

    标签: objective-c ios nsurlconnection objective-c-blocks


    【解决方案1】:

    首先,回答你的问题:

    但由于某种原因返回的 json 对象是nil。我想知道为什么?

    您返回的变量在您返回时尚未设置。您无法在 sendAsynchronousRequest:queue:completionHandler: 方法返回后立即获取结果:调用必须在回调您的块并设置 json 变量之前完成往返。

    现在简要说明如何处理它:您的方法正在尝试将异步调用转换为同步调用。如果可以的话,尽量保持异步。与其期待一个返回 NSMutableDictionary* 的方法,不如创建一个方法来获取它自己的块,并在 sendAsynchronousRequest: 方法完成时将字典传递给该块:

    - (void)executeRequestUrlString:(NSString *)urlString withBlock:(void (^)(NSDictionary *jsonData))block {
        // Prepare for the call
        ...
        // Make the call
        [NSURLConnection sendAsynchronousRequest:request
                                        queue:[NSOperationQueue currentQueue]
                            completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
            NSLog(@"dataAsString %@", [NSString stringWithUTF8String:[data bytes]]);
            NSError *error1;
            NSMutableDictionary * innerJson = [NSJSONSerialization
                JSONObjectWithData:data options:kNilOptions error:&error1
            ];
            block(innerJson); // Call back the block passed into your method
            }];
    
    }
    

    【讨论】:

      【解决方案2】:

      当您调用sendAsynchronousRequest:queue:completionHandler: 时,您请求了一个异步 请求。因此它将请求和块排队并立即返回。在将来的某个时间发出请求,然后运行完成块。但到那时,return json 早就跑了。

      如果您希望能够同步返回数据,那么您必须发出同步请求。这将挂起这个线程直到它完成,所以它不能是主线程。

      【讨论】:

        【解决方案3】:

        使用以下代码转换来自服务器的数据时检查字符串:

         NSLog(@"dataAsString %@", [NSString stringWithUTF8String:[data bytes]]);
        

        如果字符串是正确的 JSON 格式,那么只有你的 JSON 对象才是正确的。

        希望这能帮到你!!

        【讨论】:

          猜你喜欢
          • 2015-07-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-07-31
          • 2020-10-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多