2013-06-27 23 views
1

我創建了一個繼承自NSOperation的fetchImageOperation類。它使用URL獲取圖像,然後在完成時觸發該塊。我的問題是,如果我有以下代碼:NSOperation獲取圖像和更新UITableView UIImageView屬性

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"Cell"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; 

    Customer *customer = [_customers objectAtIndex:[indexPath row]]; 

    FetchImageOperation *imageOperation = [[FetchImageOperation alloc] initWithURL:[NSURL URLWithString:vegetable.imageURL]]; 

    cell.nameLabel.text = customer.name; 

    imageOperation.fetchImageOperationCompletionBlock = ^(UIImage *image) 
    { 
     [cell.thumbnailImageView setImage:image]; 
    }; 

    [_queue addOperation:imageOperation]; 

    return cell; 
} 

被稱爲主線程(UI線程),在默認情況下在setImage方法?我可以確認上面的代碼有效,它確實設置了thumbnailaImageView元素的圖像屬性。

FetchImageOperation.m文件:

@implementation FetchImageOperation 

-(id) initWithURL:(NSURL *)url 
{ 
    self = [super init]; 
    self.url = url; 
    return self; 
} 


-(void) main 
{ 
    NSData *data = [NSData dataWithContentsOfURL:_url]; 
    UIImage *image = [UIImage imageWithData:data]; 

    if(self.fetchImageOperationCompletionBlock != nil) 
    { 
     self.fetchImageOperationCompletionBlock(image); 
    } 
} 

@end 

回答

1

絕不是調用主線程自動任何用戶界面的方法。在這種情況下,將在您的NSOperation子類的main方法正在運行的任何線程上調用它。

如果你想保證所有fetchImageOperationCompletionBlock s的主線程上激發你應該使用類似

dispatch_async(dispatch_get_main_queue(), ^{ 
    if(self.fetchImageOperationCompletionBlock != nil) { 
     self.fetchImageOperationCompletionBlock(image); 
    } 
}); 

。由於單元重用,你不希望在單元本身調用屬性,而是將索引路徑保存到塊中的單元格中,然後在該索引路徑中使用單元格,或者其他內容。

0

該塊在與該操作相同的線程上被調用。所以不,它在後臺線程上調用,所以它不能正常工作。

此外,當塊完成時,您不知道單元格是否仍然用於相同的事物或者是否已被重用。

而不是做你在做什麼,看看使用類似SDWebImage

0

您可以節省電池的indexPaths和FetchImageOperation在字典應用程序完成後,才能夠控制操作進度和小區接入:

NSMutableDictionary *operations; // Define and initialise dictionary to hold operations 

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

    UIImage *image = [customer image]; 
    if (image == nil) { 
     image = [UIImage imageNamed:@"ImageHolder"]; 
     if (![[operations allKeys] containsObject:indexPath]) { 
      FetchImageOperation *imageOperation = [[FetchImageOperation alloc] initWithURL:[NSURL URLWithString:vegetable.imageURL]]; 
      imageOperation.fetchImageOperationCompletionBlock = ^(UIImage *image) { 
       // Do updates on the main thread 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath] 
        [cell.thumbnailImageView setImage:image]; 
        [operations removeObjectForKey:indexPath]; 
       }; 
      }; 
      [operations setObject:imageOperation forKey:indexPath]; 
      [_queue addOperation:imageOperation]; 
     } 
    } 
} 

// You should cancel image operations if cell goes out from the screen 
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSOperation *operation = [operations objectForKey:indexPath]; 
    [operation cancel]; 
}