하나의 진행 막대를 포함하는 창에 시트를 표시하여 Grand Central Dispatch를 사용하여 일부 긴 함수의 진행 상황을 비동기 적으로 표시하려고합니다. 나는 거의 그것을 가지고 있지만, 아마도 내가 runModalForWindow:
또는 이와 유사한 것을 사용하지 않았기 때문에 시트가 초점에있는 것처럼 보이게 할 수 없다.그랜드 센트럴 디스패치를 사용하여 무언가를 처리하는 동안 "진행"시트를 모달로 올바르게 표시하는 방법은 무엇입니까?
이것은 내가 지금 뭘하는지 약, 그것은 메인 창에서 버튼을 눌러의 결과로 발생합니다
// Prepare sheet and show it...
[NSApp beginSheet:progressSheet modalForWindow:window modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
[progressSheet makeKeyAndOrderFront:self];
[progressBar setIndeterminate:NO];
[progressBar setDoubleValue:0.f];
[progressBar startAnimation:self];
// Start computation using GCD...
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for (int i = 0; i < 1000; i ++) {
// Do some large computation here
// ...
// Update the progress bar which is in the sheet:
dispatch_async(dispatch_get_main_queue(), ^{
[progressBar setDoubleValue:(double)i];
});
}
// Calculation finished, remove sheet on main thread
dispatch_async(dispatch_get_main_queue(), ^{
[progressBar setIndeterminate:YES];
[NSApp endSheet:progressSheet];
[progressSheet orderOut:self];
});
});
이 메인 윈도우를 제외하고, 작동 초점 여전히 시트에 초점이 맞지 않고 진행 막대가 애니메이션으로 표시되지 않습니다 (setUsesThreadedAnimation:YES
을 사용하지 않은 경우).
제가 생각하는 문제는 비동기 계산을 시작하기 전에 주 스레드를 차단하지 않고 시트를 모달로 실행하는 방법을 모르겠다는 것입니다.
시트를 모달 모드로 실행하면 주 스레드를 차단해서는 안됩니다 (그렇지 않으면 메소드의 시작 부분에있는 '-beginSheet :'비트가 실행 된 후에 아무 것도 나타나지 않습니다). 나는 여기에 내 응용 프로그램에서 거의 동일한 무언가를 사용한다. (진행 상태 표시 줄이있는 모달 시트가 여기에있다.) 그리고 백그라운드에서 실행되는 GCD 블록에서 잘 업데이트된다. 시트가 아래로 미끄러지는 창의 컨트롤이 회색으로 표시되어 윈도우가 시트에 포커스를 잃어 버렸음을 나타내므로 정상적인 것처럼 보입니다. 주 스레드에서 많은 작업을 대기중인 다른 것이있을 수 있습니까? –
@BradLarson 내가 생각할 수있는 유일한 문제는 주 계산의 일부로 'dispatch_apply'를 문제가 발생시킬 수 있다고 생각할 수 있지만 표준 루프로 바꾸면 아무런 차이가 없습니다. 그렇지 않으면 메인 스레드에서 실행되는 것이 거의 없습니다. 시트 뒤에있는 메인 윈도우의 컨트롤과 여전히 상호 작용할 수 있으며 여전히 포커스가 표시됩니다 (즉, 회색으로 표시되지 않음). 예를 들어, 시트가 표시되는 동안 주 창에있는 텍스트 상자는 포커스 링과 함께 나타나고 여전히 텍스트를 입력 할 수 있습니다 (마우스로 텍스트를 선택할 수는 없지만). – Robert