我正在开发一个项目,我从另一个方法调用一个方法。在第二种方法中,我使用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;
}
提前感谢任何建议!
答案 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在他的回答中所建议的那样。