2013-08-21 24 views
0

我一直在試圖在我的項目上實現一個GCD,它顯示了從XML讀取數據,即使它是我第一次做它我已經成功(可能)實現在nameLabel和detailLabel這兩個都是字符串,但imageLabel(評論的代碼部分)不給任何東西,當我嘗試實現相同的GCD作爲兩個字符串,我不知道發生了什麼,但是當我運行該項目時,它給了一個未知的異常,我想知道如何在代碼的註釋部分實現GCD,以便我能夠在imageView中顯示圖像。在UITableView上實現NSURL的GCD

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 


    static NSString *CellIdentifier = @"CustomCell"; 

    dataFileHolder *currentData = [[xmlParser listPopulated] objectAtIndex:indexPath.row]; 
    CustomCellXMLClass *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 



    if(cell == nil) { 
     cell = [[CustomCellXMLClass alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; 
     NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCellXMLSample" owner:self options:nil]; 
     cell = [nib objectAtIndex:0]; 

    } 

    myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

    dispatch_async(myQueue, ^{ 
     NSString *nameLabel = [currentData nameOfCat]; 
     NSString *dataToCacheLabel = [myCache objectForKey:nameLabel]; 
     if(nameLabel != nil){ 
      dataToCacheLabel = [NSString stringWithString:nameLabel]; 
       if (dataToCacheLabel != nil) { 
        [myCache setObject:dataToCacheLabel forKey:nameLabel]; 
        dispatch_async(dispatch_get_main_queue(), ^{ 
        [cell.nameLabel setText:dataToCacheLabel]; 
       }); 
       } 
     } 



     NSString *detailLabel = [currentData descriptionOfCat]; 
     NSString *stringToCache = [myCache objectForKey:detailLabel]; 
     if (detailLabel != nil) { 
      stringToCache = [NSString stringWithString:detailLabel]; 
       if (stringToCache != nil) { 
        [myCache setObject:stringToCache forKey:detailLabel]; 
        dispatch_async(dispatch_get_main_queue(), ^{ 

        [cell.detailLabel setText:stringToCache]; 
        }); 
       } 
     } 

//  NSString *imageURL = [currentData imageLink]; 
//  NSData *dataToCache; 
//   if (imageURL != nil) { 
//     
//    dataToCache = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]; 
//    if (dataToCache != nil) { 
//      
//     [myCache setObject:dataToCache forKey:imageURL]; 
//     [cell.imageShow setImage:[UIImage imageWithData:dataToCache]]; 
//      
//    } 
//    else { 
//      
//     NSURL *imageURL = [NSURL URLWithString:@"http://i178.photobucket.com/albums/w255/ace003_album/190579604m.jpg"]; 
//     dataToCache = [NSData dataWithContentsOfURL:imageURL]; 
//     [myCache setObject:dataToCache forKey:imageURL]; 
//     [cell.imageShow setImage:[UIImage imageWithData:dataToCache]]; 
//    } 
//    
//   } 
     [self.activityIndicator performSelectorOnMainThread:@selector(stopAnimating) withObject:nil waitUntilDone:YES]; 

    }); 
     return cell; 

} 
+0

如果你想異步檢索圖像,使用'UIImageView'類別,比如[SDWebImage](https://github.com/rs/SDWebImage)或[AFNetworking](https:// github.com/AFNetworking/AFNetworking)。另外,你的實現是使用緩存作爲文本標籤,在這裏我看不到需要。您可能需要緩存「昂貴」的圖片請求,而不是文本標籤的設置。 – Rob

回答

3

你需要派遣,您更新單元格回主線程就像你正在做的前兩個部分。這一部分:dispatch_async(dispatch_get_main_queue(),...)它可能會是這個樣子:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"CustomCell"; 
    static NSInteger usageCount = 0; 

    dataFileHolder *currentData = [[xmlParser listPopulated] objectAtIndex:indexPath.row]; 
    CustomCellXMLClass *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

    if(cell == nil) { 
     cell = [[CustomCellXMLClass alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; 
     NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCellXMLSample" owner:self options:nil]; 
     cell = [nib objectAtIndex:0]; 
    } 

    // Give it a new tag every time, so we can tell if this is "our" use of the cell 
    cell.tag = ++usageCount; 

    myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

    dispatch_async(myQueue, ^{ 
     NSString *nameLabel = [currentData nameOfCat]; 
     NSString *dataToCacheLabel = [myCache objectForKey:nameLabel]; 
     if(nameLabel != nil){ 
      dataToCacheLabel = [NSString stringWithString:nameLabel]; 
      if (dataToCacheLabel != nil) { 
       [myCache setObject:dataToCacheLabel forKey:nameLabel]; 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        if (cell.superview && usageCount == cell.tag) 
        { 
         [cell.nameLabel setText:dataToCacheLabel]; 
        } 
       }); 
      } 
     } 

     NSString *detailLabel = [currentData descriptionOfCat]; 
     NSString *stringToCache = [myCache objectForKey:detailLabel]; 
     if (detailLabel != nil) { 
      stringToCache = [NSString stringWithString:detailLabel]; 
      if (stringToCache != nil) { 
       [myCache setObject:stringToCache forKey:detailLabel]; 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        if (cell.superview && usageCount == cell.tag) 
        { 
         [cell.detailLabel setText:stringToCache]; 
        } 
       }); 
      } 
     } 

     NSURL *fallbackImageURL = [NSURL URLWithString:@"http://i178.photobucket.com/albums/w255/ace003_album/190579604m.jpg"]; 
     NSString *imageURL = [currentData imageLink]; 
     NSArray* urls = imageURL ? @[ imageURL, fallbackImageURL ] : @[ fallbackImageURL ]; 
     for (NSURL* url in urls) 
     { 
      UIImage* cachedImage = [myCache objectForKey: url]; 
      if (!cachedImage) 
      { 
       NSData* imageData = [NSData dataWithContentsOfURL:url]; 
       cachedImage = [UIImage imageWithData:dataToCache]; 
       [myCache setObject:cachedImage forKey:url]; 
      } 

      if (cachedImage) 
      { 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        if (cell.superview && usageCount == cell.tag) 
        { 
         [cell.imageShow setImage: uiImage]; 
        } 
       }); 
       break; 
      } 
     } 
    }); 
    return cell; 
} 

從長遠來看,你應該也考慮任何數量的異步加載的方法,而不是dataWithContentsOfURL:這將阻止後臺線程等待的數據將被完全接收。但這是一個二階問題,而不是你問到的問題。

編輯:編輯@ Rob的評論。在提取之前檢查緩存中的預緩存圖像,並防止將值寫入重複使用或不可見的單元格中(假設您沒有將tag用於其他功能)。但實際上,只需使用異步圖像下載管理器即可。

+0

我做到了,順便說一下,我可以在隊列的開頭添加一個UIActivityIndi​​cator,以便在解析數據時用戶可以在前面看到UIActivityIndi​​cator,或者在UIActivityIndi​​cator代碼的位置提供建議。 –

+2

這裏有幾個問題:首先,您必須檢查以確保「單元格」仍然可見(即在完成圖像檢索時單元格未被重新用於另一行)。上面的代碼可能會暫時更新慢速網絡上的錯誤行!其次,您應該認識到,如果您在表格中快速向下滾動,此實現將不會檢索當前圖像,直到先前的行完成檢索(即倒退!)。比修復上面的代碼更容易,你應該使用任何的異步圖像檢索'UIImageView'類別,如SDWebImage。 – Rob

+0

@Rob對於所有這些都是非常正確的;我只是試圖回答所問的問題。 – ipmcc