dataWithContentsOfURL与downloadTaskWithURL

时间:2014-06-13 13:31:16

标签: ios ios7

当我使用从其他Web服务检索到的url获取图像数据时,我需要更新模型对象,我总是在更新相应的视图时遇到问题。基本上,这是问题:

  1. 调用Web服务A
  2. 检索图片网址 - 首次调用返回阻止
  3. 使用图片网址调用网络服务
  4. 检索图像数据
  5. 使用图像数据更新模型对象
  6. 基于模型对象更新视图对象缩略图(例如:uicollectionviewcell或uitableviewcell)(此处出现问题)
  7. 我之前在AFNetworking中使用过这种方法,相应地,NSURLSession。但是,问题是,在更新了模型对象之后,我需要在缩略图图像出现之前滚动集合视图或表视图。否则,在首次加载时,图像保持空白。

    请参阅以下代码,了解此方法的示例:

    - (void)searchFlickrForTerm:(NSString *) term completionBlock:(FlickrSearchCompletionBlock) completionBlock
    {
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration  defaultSessionConfiguration];
    _session = [NSURLSession sessionWithConfiguration:config
                                             delegate:self
                                        delegateQueue:nil];
    
    NSString *requestString = [Flickr flickrSearchURLForSearchTerm:term];
    NSURL *url = [NSURL URLWithString:requestString];
    NSURLRequest *req = [NSURLRequest requestWithURL:url];
    
    NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
        if (error != nil) {
            completionBlock(term,nil,error);
        }
        else{
            NSDictionary *searchResultsDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
            //This is the segment where we parse the Flickr data
            NSString * status = searchResultsDict[@"stat"];
            if ([status isEqualToString:@"fail"]) {
                NSError * error = [[NSError alloc] initWithDomain:@"FlickrSearch" code:0 userInfo:@{NSLocalizedFailureReasonErrorKey: searchResultsDict[@"message"]}];
                completionBlock(term, nil, error);
            } else {
    
                NSArray *objPhotos = searchResultsDict[@"photos"][@"photo"];
                NSMutableArray *flickrPhotos = [@[] mutableCopy];
                for(NSMutableDictionary *objPhoto in objPhotos)
                {
                    //Good Idea to parse in the web service call itself. The structure might be different
                    //If parse in the model class, can be very complicated if the structure is different
                    FlickrPhoto *photo = [[FlickrPhoto alloc] init];
                    photo.farm = [objPhoto[@"farm"] intValue];
                    photo.server = [objPhoto[@"server"] intValue];
                    photo.secret = objPhoto[@"secret"];
                    photo.photoID = [objPhoto[@"id"] longLongValue];
    
                    NSString *searchURL = [Flickr flickrPhotoURLForFlickrPhoto:photo size:@"m"];
                    //Call to retrieve image data
                    NSURLSessionDownloadTask *getImageTask = [_session downloadTaskWithURL:[NSURL URLWithString:searchURL] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error){
                        UIImage *downloadImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:location]];
                        photo.thumbnail = downloadImage;
                    }];
    
                    [getImageTask resume];
                    [flickrPhotos addObject:photo];
                }
    
                completionBlock(term,flickrPhotos,nil);
            }
            //End parse of Flickr Data
        }
    }];
    
    [dataTask resume];
    //End
    }
    

    在上面的代码段中,在我解析了FlickrPhoto模型对象之后,我使用NSURLDownloadTask来调用图像的url。这是有问题的代码段。

    方法A:

    NSURLSessionDownloadTask *getImageTask = [_session downloadTaskWithURL:[NSURL URLWithString:searchURL] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error){
        UIImage *downloadImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:location]];
         photo.thumbnail = downloadImage;
    }];
    
    [getImageTask resume];
    

    但是,如前所述,即使我更新了photo.thumbnail属性,在我的uicollectionview中我将我的imageView设置为从缩略图属性中读取,除非我滚动,否则图像不会显示在我的集合视图中。

    然而,有趣的是,不是使用NSURLDownloadTask,而是使用dataWithContentsOfURL,而是在不需要滚动集合视图的情况下显示图像。

    方法B:

    NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:searchURL]
                                                              options:0
                                                                error:&error];
    UIImage *image = [UIImage imageWithData:imageData];
    photo.thumbnail = image;
    

    我不知道为什么会这样。我还通过抓取视图控制器中的主线程来重新加载集合视图数据。

    dispatch_async(dispatch_get_main_queue(), ^{
                [self.collectionView reloadData];
            });
    

    我真的为这篇冗长的帖子道歉,但如果有人能就此提出建议,我真的很感激。我已经阅读了文档,但我仍然能够找到这个令人费解的问题的有意义的答案。

1 个答案:

答案 0 :(得分:0)

在仔细研究Apple的文档后,我想我知道这个问题。

基本上,在我的方法A中,downloadTaskWithURL将分拆另一个后台线程。因此,即使我更新了模型对象,也不会使用新信息更新视图,除非我再次获取主线程并刷新视图。

但是,在方法B中,dataWithContentsOfURL同步运行。因此,根本没有后台线程的问题。

来自苹果文档:

  

<强> dataWithContentsOfURL:   返回包含给定URL指定位置的数据的数据对象。

     

<强>讨论   此方法非常适合将data:// URL转换为NSData对象,也可用于读取同步的短文件。如果您需要读取可能较大的文件,请使用inputStreamWithURL:打开流,然后一次读取一个文件。

如果我理解错误,请随时纠正我。如果我认为解决方案可以更好地解决我的疑虑,我很乐意将我接受的答案改为你的答案。