2013-06-27 3 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; 
} 

setImage 메서드가 기본 스레드 (UI 스레드)에서 기본적으로 호출 되었습니까? 위 코드가 작동하고 thumbnailaImageView 요소의 image 속성을 설정하는지 확인할 수 있습니다.

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

어떠한 방식은 자동으로 메인 스레드에 어떤 UI 메소드의 호출입니다. 이 경우에는 NSOperation 하위 클래스의 main 메서드가 실행중인 스레드에서 호출됩니다. 당신은 모든 fetchImageOperationCompletionBlock의 메인 스레드에서 해고 보장하려면

당신은

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

같은 것을 사용한다. 셀 재사용으로 인해 셀 자체에서 속성을 호출하지 않고 대신 블록의 셀에 인덱스 경로를 저장하고 해당 인덱스 경로에서 셀을 사용하는 등의 작업을 수행 할 수 있습니다.

0

블록이 작업과 동일한 스레드에서 호출됩니다. 아니요, 백그라운드 스레드에서 호출되었으므로 제대로 작동하지 않습니다.

또한 블록이 끝나면 셀이 동일한 용도로 계속 사용되고 있는지 또는 재사용되었는지 알 수 없습니다.

무엇을하고있는 것보다 SDWebImage 같은 것을 사용하십시오.

당신은 응용 프로그램이 완료된 후 작업 진행과 세포에 대한 액세스를 제어 할 수 있도록 사전에 셀의 indexPaths 및 FetchImageOperation을 절약 할 수
0

:

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]; 
} 
관련 문제