2009-08-17 4 views
3

보기를 업데이트하는 백그라운드 작업이 있습니다. 이 태스크는 -setNeedsDisplay를 호출하여 뷰를 가져옵니다.문제를 묻는 백그라운드 작업에서 -setNeedsDisplay를 호출합니까?

이 작동 :

- (void) drawChangesTask; 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    if (pixels) { 
     drawChanges((UInt32 *) origPixels, (UInt32 *) pixels, CGBitmapContextGetBytesPerRow(ctx)/4, CGBitmapContextGetHeight(ctx), count--); 

     if (count < 0) { 
      count = 150; 
     } 
     else 
      [self performSelectorInBackground:@selector(drawChangesTask) withObject:nil ]; 

     [self performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO ]; 

    } 
    [pool release]; 
} 

이 작동하지 않습니다

- (void) drawChangesTask; 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    if (pixels) { 
     drawChanges((UInt32 *) origPixels, (UInt32 *) pixels, CGBitmapContextGetBytesPerRow(ctx)/4, CGBitmapContextGetHeight(ctx), count--); 

     if (count < 0) { 
      count = 150; 
     } 
     else 
      [self performSelectorInBackground:@selector(drawChangesTask) withObject:nil ]; 

     [self setNeedsDisplay]; 

    } 
    [pool release]; 
} 

사람은 이유를 알고? 그것이 작동하지 않는다고 말할 때, 수십 반복을 실행하는 것을 의미합니다. 때로는 이미지의 일부가 위아래로 이동하거나 전체적으로 비어있는 것을보고, 그 다음에 Deugger가 CoreGraphics 어딘가에서 "EXC_BAD_ACCESS"을 제공합니다.

또한 autorelease 풀을 직접 처리하지 않으면 누출 오류 메시지가 나타납니다. 그 이유가 무엇인지 이해하지 마십시오. 내 drawChanges()는 새로운 객체를 만들지 않습니다. 여기서 오류는 다음과 같습니다

2009-08-17 11:41:42.358 BlurApp[23974:1b30f] *** _NSAutoreleaseNoPool(): Object 0xd78270 of class NSThread autoreleased with no pool in place - just leaking 

답변

8

UIKit 간단하지 스레드 안전 - 당신은 주 스레드에서 제어 UIKit 업데이트하는 방법을 호출해야합니다.

나는이 줄 생각 :

[self performSelectorInBackground:@selector(drawChangesTask) withObject:nil]; 

이 문제를 일으키는입니다. 당신은 단순히 현재 스레드에서 다시 호출 해 보았습니까? 당신이 호출 사이에 실행하는 runloop 필요한 경우, 사용

[self performSelector:@selector(drawChangesTask) withObject:nil afterDelay:0.0]; 

이것은 당신이 완료에있어 그리고 runloop 라운드 한 번 갔다 방법 후 현재 스레드에서 메소드를 호출합니다.

+0

예, performSelectorInBackground없이 직접 호출하면 runloop이 실행되어 drawRect를 호출 할 기회를 얻지 못합니다. 당신이 애프터 델리라고 부르는대로하면, 이상한 충돌없이 작동합니다. – mahboudz

+1

이것은 또한 [self performSelectorOnMainThread : @selector (setNeedsDisplay) withObject : nil waitUntilDone : NO]를 사용할 때 작동하는 이유를 설명합니다. setNeedsDisplay를 호출합니다. performSelectorInBackground는 drawChangesTask와 동일한 함수/메서드를 호출하고 drawChanges() 함수는 UIKit을 호출하지 않습니다. 따라서 스레드 감도가있는 것처럼 보이는 것은 setNeedsDisplay뿐입니다. 주 스레드에서이를 수행하면 문제가 없습니다. – mahboudz

+0

나는 performSelector가 performSelectorOnMainThread에 의해 호출 된 0과 performSelector 또는 performSelectorInBackground의 두 가지 해결책을 가지고있다. – mahboudz

2

문제는 여기에 당신이 보장되는 배경 스레드 nothign에서 뭔가를 당신의 UI를 말한다면 UIKit는 스레드로부터 안전하지 않습니다이다, 싶은 당신의 UI 요소에 대한 업데이트를 수행 할 performSelectorOnMainThread 방법을 사용하는 것입니다

관련 문제