当我使用从其他Web服务检索到的url获取图像数据时,我需要更新模型对象,我总是在更新相应的视图时遇到问题。基本上,这是问题:
我之前在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];
});
我真的为这篇冗长的帖子道歉,但如果有人能就此提出建议,我真的很感激。我已经阅读了文档,但我仍然能够找到这个令人费解的问题的有意义的答案。
答案 0 :(得分:0)
在仔细研究Apple的文档后,我想我知道这个问题。
基本上,在我的方法A中,downloadTaskWithURL将分拆另一个后台线程。因此,即使我更新了模型对象,也不会使用新信息更新视图,除非我再次获取主线程并刷新视图。
但是,在方法B中,dataWithContentsOfURL同步运行。因此,根本没有后台线程的问题。
来自苹果文档:
<强> dataWithContentsOfURL:强> 返回包含给定URL指定位置的数据的数据对象。
<强>讨论强> 此方法非常适合将data:// URL转换为NSData对象,也可用于读取同步的短文件。如果您需要读取可能较大的文件,请使用inputStreamWithURL:打开流,然后一次读取一个文件。
如果我理解错误,请随时纠正我。如果我认为解决方案可以更好地解决我的疑虑,我很乐意将我接受的答案改为你的答案。