2010-04-30 5 views
4

UIViewControllerdealloc을 백그라운드 스레드에서 호출하는 것은 오류입니까?배경 스레드에 dealloc

부울 _WebTryThreadLock (부울) : UITextView은 (? CAN) 결국 결과 _WebTryThreadLock를 호출 할 것으로 보인다 메인 스레드 또는 웹 스레드가 아닌 다른 스레드 에서 웹 잠금을 얻기 위해 노력했다. 보조 스레드에서 UIKit에 을 호출 한 결과 일 수 있습니다.

배경 : 나는 selector하고 알리는 target 오브젝트를 서브 클래 싱 NSOperation 있습니다. NSOperation이 실행에 주위를 얻을 때 UIViewController가 이미 기각 된 경우

-(id)initWithTarget:(id)target { 
    if (self = [super init]) { 
     _target = [target retain]; 
    } 
    return self; 
} 

-(void)dealloc { 
    [_target release]; 
    [super dealloc]; 
} 

release에 대한 호출은 백그라운드 스레드에 dealloc의 트리거합니다.

+0

[내 솔루션 (NSTimer를 사용하여 마지막 스레드를 주 스레드로 강제 실행)] (http : // stackoverflow.com/questions/6353471/block-release-deallocating-ui-object-on-a-background-thread/6482941 # 6482941 "내 솔루션") – Jeff

답변

7

예, 백그라운드 스레드 (또는 큐)에서 UIViewController를 해제하는 것은 오류입니다. UIKit에서 dealloc은 스레드로부터 안전하지 않습니다. 이 명시 적으로 애플의 TN2109 문서에 설명되어 있습니다 :

보조 스레드가 대상 개체를 유지하면 스레드 해제 메인 스레드 전에 참조가 개체에 대한 마지막 참조를 해제한다는 것을 보장해야한다. 이 작업을 수행하지 않으면 개체에 대한 마지막 참조가 보조 스레드에 의해 해제되므로 개체의 -dealloc 메서드가 해당 보조 스레드에서 실행됨을 의미합니다. 객체의 -dealloc 메소드가 보조 스레드에서 수행하기에 안전하지 않은 작업을 수행하는 경우 문제가 발생합니다. 이는보기 컨트롤러와 같은 UIKit 객체에 공통적 인 작업입니다.

+1

4 년 후 올바른 답이 나타납니다! 좋은 직장 - 테네시는 내 질문 후 몇 달 간 출판되었으므로이 행동으로 인해 혼란스럽지 않은 것 같습니다. –

6

간단한 규칙은 배경 스레드의 UI*에있는 무엇이든을 수행하는 것이 오류라는 것입니다.

+0

'performSelectorOnMainThread'는 어떻게됩니까? 어디에서 문서화되어 있습니까? 내가 본 모든 것은 "백그라운드 스레드에서 UI를 조작하지 마십시오"라는 다소 모호한 참조입니다. 이는 * * *보다 훨씬 덜 제한적입니다. –

+2

performSelectorOnMainThread를 호출하는 일반적인 방법은 : 백그라운드 스레드에서 UI를 조작하려는 경우입니다. – schaechtele

+0

@schaechtele - 다른 객체에서 크로스 스레드 호출을 할 때 [UIViewController performSelectorOnMainThread :] 또는 [self performSelectorOnMainThread :]를 호출합니까? –

3

두 번째 게시물에는 유용한 정보가 있지만 그 대답은 나에게 적합하지 않았습니다.

UIWebView in multithread ViewController

이 아이폰 OS 4에서 해결하지만, 확인되지 않은 수 있음을 보인다.

[NSThread isMainThread]가 NO 일 때 컨트롤러의 dealloc에서 UIWebView를 공개하지 않게되었습니다. 오히려 충돌보다 누출 될 것입니다 (더 나은 솔루션을 얻을 때까지).

+0

예 - 동일한 문제입니다. 나는 단지 주 스레드에서 릴리스를 수행하여 그것을 해결했지만, sutorekease도 잘 동작 할 것이라고 나는 생각한다. 내 주된 관심사는 ObjC에서 예상 된 동작인지 아닌지입니다. 아이폰 4가 바뀌 었는지 확인해야한다. 적어도 버그 일 수 있다는 증거를 줄 것이다. –

+0

iOS4에서 "고정"이라고 생각합니다. 최소한 피겨 테스트를 기반으로합니다. – Jason

2

언제든지 dealloc을 호출하면 오류가 발생합니다. 당신은 오직 릴리스를 호출해야합니다.

백그라운드 스레드에서 UI 관련 인스턴스에 액세스하면 안됩니다. 여기에는 내부적으로 사물을 수정할 수 있기 때문에 getter 메소드 사용이 포함됩니다. 그러나 retain 및 release에 대한 일반적인 규칙이 준수되는 한 retain 및 release는 언제든지 객체에 대해 스레드로부터 안전합니다. UI 관련 인스턴스에는 활성 UIView 또는 UIViewController에서 참조하는 모든 개체가 포함됩니다.

performSelectorOnMainThread는 주 스레드에 도착할 때까지 개체를 유지하는 것 이상을 수행하지 않습니다. 모든 UI 관련 객체에서 호출하는 것이 안전합니다.

+0

오른쪽. 나는 릴리스만을 호출하지만, 마지막 릴리스이므로 내부적으로 dealloc을 호출하게된다. release가 쓰레드에 영향을 미치지 않는다면, dealloc 역시 잘되어야한다. 그래서 _WebTryThreadLock은 규칙에 대한 (버그가있는) 예외일까요? –