如何延迟方法,直到NSData在NSUrlSession中加载完成?

时间:2014-11-29 08:35:31

标签: ios asynchronous nsurlsession

我正在开发一个项目,我从另一个方法调用一个方法。在第二种方法中,我使用NSURLSession从服务器获取数据。当第二个方法将NSData返回到第一个方法时,数据将转换为JSON,然后返回到对第一个方法进行初始调用的viewcontroller。我遇到的问题是第一个方法是返回一个null对象,因为NSData加载速度不够快。我不知道该怎么办。

以下是代码:

方法1

-(NSDictionary*)returnJsonDictionaryFromUrl:(NSURL*)url {

    NSData *data = [self makeHttpRequestWithUrl:url];
    //NSLog(@"Data is: %@", data);
    NSError *error;

    NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data
                                                         options:kNilOptions error:&error];


    return json;

}

方法2

-(NSData*)makeHttpRequestWithUrl:(NSURL*)url {

    if (!_data) {
        _data = [[NSData alloc]init];
    }

    NSURLSession *session = [NSURLSession sharedSession];
    [[session dataTaskWithURL:url
            completionHandler:^(NSData *data,
                                NSURLResponse *response,
                                NSError *error) {

                _data = data;


            }] resume];



    return _data;
}

提前感谢任何建议!

2 个答案:

答案 0 :(得分:1)

因此,默认情况下,块会在执行时跳过并排队(有时在其他线程上)。这意味着当您返回一个刚刚在块中设置的变量时,您应该假设该块尚未执行,并且您在其中设置的任何变量将在很久之后才会设置。

处理此问题的最佳方法是将完成块传递给方法。因此,不是让它返回NSData指针,而是使它成为一个空,并简单地将完成块传递给它。这将是您的请求方法:

-(void)makeHttpRequestWithUrl:(NSURL*)url completion:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completion {
    NSURLSession *session = [NSURLSession sharedSession];
    [[session dataTaskWithURL:url
            completionHandler:completion] resume];
}

你会这样称呼它:

[object makeHttpRequestWithUrl:url completion:^(NSData *data, NSURLResponse *response, NSError *error) {
   // handle error
   // use data
}

答案 1 :(得分:1)

如果您真的必须执行同步Web请求,则NSURLSession不是正确的工具。为此,我们有NSURLConnection sendSynchronousRequest:returningResponse:error:。如果你甚至不关心HTTP响应,你也可以使用NSData dataWithContentOfURL:。

但是你真的不应该使用它们,特别是在主线程上,因为如果网络请求花费太长时间,这将导致你的应用程序崩溃。接受网络请求的异步性质并在完成块中处理您的数据,正如kpsharp在他的回答中所建议的那样。