2012-02-01 3 views
9

대기열을 사용하는 주 스레드에서 UI를 업데이트하는 것과 관련된 한 가지 질문이 있습니다.dispatch_get_main_queue()의 UI 업데이트

음, 우리가 UITableView를 가지고 UIImageView로 UILabel을 보여주는 것을 가정 해 봅시다. 있는 UIImage의 사용하여 .. prepareCellfor 비동기 로딩된다

dispatch_async(t_queue, ^{ 
    //load image 
    //dispatch_async(dispatch_get_main_queue(),^{ 
    cell.imageView = image; 
    } 
}); 

하지만, 블록은 이미지를 가져 오는 동안 사용자가 하나의 셀 (또는 네비게이션 뷰 컨트롤러 뒤로 버튼)이 셀 DetailViewController 드 하중 (가압

또는 앱으로 돌아갑니다).

제 질문은 : 블록이 메인 스레드를 실행하여 셀의 imageView를 업데이트하면 어떻게 될까요? 이것은 좋은 질문입니다 ...

감사

답변

14

그것을 창에로드되지 않은있는 UIView를 업데이트하려고하거나 심지어는 언로드되어 있습니다. 그리고 대답은 ARC을 사용할 때 본질적으로 블록 자체가 객체를 보유하므로 나중에 처리 될 것입니다. 그 미묘한 기억의 하나입니다. 이 셀이 오는 UITableView이 할당 해제되어 모든 셀을 해제하면이 셀은 유지되고 (화면이 꺼지더라도) cell.imageView = image;이라는 할당이 완료되면 해제됩니다.

나는 제어 된 실험의 큰 팬이며 이것을 시험하기 위해 착수했지만, UITableView에는 많은 움직이는 부분 (의도적 인 말장난 없음)이 있습니다. 그래서 다음과 같이 간단한 NSObject 서브 클래스를 사용하여 매우 간단한 실험을 만든 :

분명히이 클래스는 나에게 블록 ( sayHello)에서 호출 할 수있는 기능을 제공하기위한 것입니다 및 때 NSLog 할당 해제 생산합니다
@implementation SayHello 
-(void)sayHello{ 
    NSLog(@"Hello"); 
} 
-(void)dealloc{ 
    NSLog(@"SayHello dead"); 
} 
@end 

.

내가 이렇게 내 테스트를 실행 :

SayHello *hello = [[SayHello alloc] init]; 
dispatch_async(dispatch_get_global_queue(0, 0), ^{ 
    double delayInSeconds = 30.0; 
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
     [hello sayHello]; 
    }); 
}); 

30 초에도 (사실,이 유지되지 않은, 경우) "안녕하세요"개체의 할당을 해제 할 수있는 가장 게으른 runloop 시간을 제공합니다. 그러나 30 초 동안 콘솔은 조용합니다. 30 초가 지나면 "Hello"메시지가 나오고 "SayHello dead"메시지가 나옵니다.

어떻게 이것이 "잡았다"? 글쎄, 분명히 Blocks/ARC가 이것을하고 있다는 것을 깨닫지 못한다면, 그것은 사라져야한다고 생각했던 것을 유지할 수 있습니다. 그러나 또한 당신의 예를 들어 UITableViewCell; 셀이 한 번 표시되고 이미지를 얻기 위해 네트워크를 통해 요청을 보내지 만 블록이 이미지를 기다리는 동안 셀이 다시 사용되면 어떻게됩니까? 이제 이미지를 설정하려고하는 셀을 참조하는 두 번째 블록이 있습니다. 자, 이제 당신은 패자가 어떤 이미지가 표시 될지 결정할 경주가 있습니다.