Ios dataWithContentsOfURL与downloadTaskWithURL

Ios dataWithContentsOfURL与downloadTaskWithURL,ios,ios7,Ios,Ios7,当我使用从另一个web服务检索的url获取图像数据,并且需要更新模型对象时,更新相应的视图总是有问题。基本上,问题是: 将Web服务称为 检索图像URL-第一次调用返回块 使用图像URL调用Web服务 检索图像数据 使用图像数据更新模型对象 基于模型对象更新视图对象缩略图(例如:uicollectionviewcell或uitableviewcell)(此处出现问题) 我以前在AFNetworking和相应的NSURLSession中使用过这种方法。但是,问题是,在更新模型对象之后,我需要在缩略

当我使用从另一个web服务检索的url获取图像数据,并且需要更新模型对象时,更新相应的视图总是有问题。基本上,问题是:

  • 将Web服务称为
  • 检索图像URL-第一次调用返回块
  • 使用图像URL调用Web服务
  • 检索图像数据
  • 使用图像数据更新模型对象
  • 基于模型对象更新视图对象缩略图(例如:uicollectionviewcell或uitableviewcell)(此处出现问题)
  • 我以前在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.缩略图属性之后,在我的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];
            });
    

    我真的为这篇冗长的帖子道歉,但如果有人能给我提供建议,我将不胜感激。我已经阅读了文档,但我仍然能够找到这个令人困惑的问题的有意义的答案

    好吧,在仔细研究了苹果的文档之后,我想我知道了这个问题

    本质上,在我的方法中,downloadTaskWithURL将派生出另一个后台线程。因此,即使我已经更新了模型对象,视图也不会用新信息更新,除非我再次抓取主线程并刷新视图

    然而,在方法B中,dataWithContentsOfURL同步运行。因此,根本不存在背景线程的问题

    来自apple文档:

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

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

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