2011-09-08 1 views
1

HyUIWebView EXC_BAD 액세스

UIView가 있습니다. 한 가지 방법으로 WebView를 할당하고 retain 속성으로 설정합니다.

self->webView= [[UIWebView alloc] initWithFrame:self.frame]; 

그런 다음 HTML 문자열을로드하기 시작합니다. 로드 된 후에는 크기 조정을 위해 뷰의 크기를 조정하고 수퍼 뷰에 대한 콜백을 시작합니다. 효과가 있습니다. 내 문제는보기가로드되기 전에 사용자가 돌아 가면보기가 해제된다는 것입니다. 그럼 내 WebView는 BAD_ACCESS를 던집니다.

-(void)dealloc{ 
[self.webView setDelegate:nil]; 
[self.webView stopLoading]; 
[self setWebView:nil]; 
[htmlStr release]; 
[super dealloc];} 

콜백 추적이 화면에 표시되어 다음은 할당 해제의 방법이다. 흥미로운 점은 WebView를 공개하지 않으면 매력과 같은 것입니다. 나는 웹보기를 해제하면 할당이 해제 때, 다음, 나는 로그에 오류 메시지가 :

![bool _WebTryThreadLock(bool), 0x4e05150: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...][1] 

편집 : 그것은 수정되었습니다. 내 이미지 로딩 방법이 유죄라는 것이 밝혀졌습니다. 이미지를로드하고 완료되면 performSelectorOnMainThred :를 만들기 위해 새 스레드 (NSOperationQueue 및 NSInvocationOperation)를 시작했습니다. 정말 큰 오버 헤드였던 모든 페이지 전환에 수백 개의 작은 (1-2 KB) 이미지를로드했습니다. 하나의 스레드에서 이미지를 하나씩 다운로드하는 방법을 쓸 때이 버그가 다시는 발생하지 않았습니다.

+0

동일한 뷰의'viewWillDisappear'에서'[self.webView setDelegate : nil];을 호출 해보십시오. – Nekto

+0

당신이하는 일을 정확히 알지 못하는 경우 -> 표기법을 사용하여 객체에 변수를 설정하지 마십시오. 거의 정확하지 않습니다. 일반적인'setWebView :'또는'self.webView ='표기법을 사용하십시오. –

답변

1

메인이 아닌 다른 트레드에서 UI를 수정하고 있습니다. UIKit은 스레드로부터 안전하지 않으므로 (따라서 충돌이 ...)이 작업은 금지됩니다. 다른 스레드에서 UI를 수정하려면, 당신은 사용해야합니다 : 난 당신의 코드에 통보했습니다

performSelectorOnMainThread:withObject:waitUntilDone: 

다른 것은 잘못 -dealloc에 속성을 해제한다는 것입니다. 당신은이 같은 세터를 합성 사용하지 않아야합니다 :

[self setWebView:nil]; // same as self.webView = nil; 

당신은해야하지, 당신 특성에 KVO (키 - 값 관측)를 사용하여 시작하면 그것은 당신에게 많은 문제를 가져올 수 있기 때문에 ... 대신 그냥 쓰기 :

[webView release]; 

또는, 당신은 "The Heisenbug" 피하려면 :

[webView release], webView = nil; 

편집 : 당신은 또한에 답 혜택을 누릴 수 있습니다 이 SO 질문 : How to safely shut down a loading UIWebView in viewWillDisappear?

+0

나는 UI를 변조하지 않을거야. webview를 포함하는보기는 배열에 저장됩니다. 기본 뷰를 다시 초기화해야 할 때 뷰를 superview에서 제거하고 dealloc이 호출 된 [array removeAllObject]를 호출하고 webview를 포함하는 childView dealloc이 호출됩니다 (dealloc 메소드 게시시). 배열의 릴리스는 메인 스레드에 있지만, dealloc은 – MetaImi

+0

다른 스레드에서 호출됩니다. 그것이 무료 리소스를 가지고 있기 때문에 시스템이 그것을 부르는 것 같아요. 나는 당신이 링크 한 것을 해봤지만, 내부 웹 뷰 dealloc이 불려질 때 로딩을 멈추었고, 충돌했다. – MetaImi

0

그나마 그냥 webView을 사용,의 dealloc에서 self.webView로 전화 : 그것은 수정되었습니다

- (void)dealloc { 
    if ([webView isLoading]) 
     [webView stopLoading]; 
    [webView setDelegate:nil]; 
    [webView release], webView = nil; 
    [super dealloc]; 
} 
+0

'if ([webView isLoading]) 불필요 - 'webView stopLoading'을 호출하면 아무 것도로드되지 않으면 아무 일도 일어나지 않습니다. – matm

+0

잘 알고 있습니다. 고마워요! – chown

0

. 내 이미지 로딩 방법이 유죄라는 것이 밝혀졌습니다. 이미지를로드하고 완료되면 performSelectorOnMainThred :를 만들기 위해 새 스레드 (NSOperationQueue 및 NSInvocationOperation)를 시작했습니다. 정말 큰 오버 헤드였던 모든 페이지 전환에 수백 개의 작은 (1-2KB) 이미지를로드했습니다. 한 스레드 씩 이미지를 다운로드하는 메서드를 작성할 때이 버그는 다시는 발생하지 않았습니다.