2014-06-13 54 views
2

當我使用從其他Web服務檢索到的URL獲取圖像數據時,我需要更新模型對象,但我總是在更新相應視圖時遇到問題。從本質上講,這裏的問題:dataWithContentsOfURL與downloadTaskWithURL

  1. 呼叫Web服務的
  2. 檢索圖片網址 - 第一個調用返回使用圖像URL
  3. 檢索圖像數據
  4. 更新模型對象與阻止
  5. 調用Web服務圖像數據
  6. 更新視圖對象縮略圖(例如: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.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

好吧我認爲我知道這個問題後,密切研究蘋果的文件。

本質上,在我的方法A中,downloadTaskWithURL將分離出另一個後臺線程。因此,即使我更新了模型對象,除非我再次抓住主線程並刷新視圖,否則視圖將不會被新信息更新。

但是,在方法B中,dataWithContentsOfURL同步運行。因此,根本沒有後臺線程的問題。

從蘋果文檔:

dataWithContentsOfURL: 返回包含從由一個給定的URL所指定的位置的數據的數據對象。

討論 這種方法是理想的用於轉換數據:// URL來NSData的對象,並且還可以用於讀短文件同步。如果您需要讀取潛在的大文件,請使用inputStreamWithURL:打開一個流,然後逐個讀取文件。

如果我的理解錯了,請隨時糾正我。如果我認爲解決方案能更好地解決我的疑問,我很樂意將我接受的答案更改爲您的答案。

相關問題