2011-01-10 6 views
0

사용자가 버튼을 클릭 한 후 복잡한 (즉, 긴) 작업을 실행해야합니다. 버튼을 누르면 시트가 열리고 dispatch_async 및 기타 Grand Central Dispatch 항목을 사용하여 장기 실행 작업이 시작됩니다.시트 및 장기 실행 작업

나는 코드를 작성했지만 올바르게 작동하지만 모든 것이 올바르게 수행되었거나 (내 무지로 인해) 잠재적 문제를 무시한 경우 이해가 도움이 필요합니다.

사용자가 버튼을 클릭하고 시트를 열어 블록이 예에서 만이 (;;) 루프 위한 블록이 작업이 완료 될 때 시트를 닫고 또한 로직을 포함 실행 (긴 작업을 포함한다.

-(IBAction)openPanel:(id)sender { 
    [NSApp beginSheet:panel 
     modalForWindow:[self window] 
     modalDelegate:nil 
     didEndSelector:NULL 
      contextInfo:nil]; 

    void (^progressBlock)(void); 
    progressBlock = ^{ 

     running = YES; // this is a instance variable 

     for (int i = 0; running && i < 1000000; i++) { 
      [label setStringValue:[NSString stringWithFormat:@"Step %d", i]]; 
      [label setNeedsDisplay: YES]; 
     } 
     running = NO; 
     [NSApp endSheet:panel]; 
     [panel orderOut:sender]; 

    }; 

    //Finally, run the block on a different thread. 
    dispatch_queue_t queue = dispatch_get_global_queue(0,0); 
    dispatch_async(queue,progressBlock); 
} 

패널은 사용자가 완성이 코드는 상태 텍스트의 값을 설정하는 잠재적 인 문제가

-(IBAction)closePanel:(id)sender { 
    running = NO; 
    [NSApp endSheet:panel]; 
    [panel orderOut:sender]; 
} 

답변

2

전에 작업을 중지 할 수있는 정지 버튼이 포함되어 있습니다. 기본적으로 AppKit의 모든 개체는있다 f라고 부르는 것이 허용된다. rom의 메인 스레드와 이상한 방법으로 휴식을 취할 수없는 경우. 글로벌 대기열이 실행중인 모든 스레드의 레이블에서 setStringValue:setNeedsDisplay: 메소드를 호출합니다. 이 문제를 해결하려면 당신과 같이 루프를 작성해야 : AppKit의 기대로

for (int i = 0; running && i < 1000000; i++) { 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [label setStringValue:[NSString stringWithFormat:@"Step %d", i]]; 
     [label setNeedsDisplay: YES]; 
    }); 
} 

이 메인 스레드에서 레이블 텍스트를 설정합니다.

관련 문제