2014-09-03 2 views
0

현재 자체 이벤트 루프를 실행하는 응용 프로그램을 개발 중입니다. 다른 디스패치에서 큐에 대기하지 않을 때 디스패치 비동기를 사용하면 해당 블록이 올바르게 실행됩니다.NSApp nextEventMatchingMask (디스패치 내 디스패치)

예는 : 나는 이것을 실행하면 예상대로

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
      NSLog(@"This should appear!"); 
     }); 

for (;;) 
{ 
    NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask 
               untilDate:[NSDate distantPast] 
                inMode:NSDefaultRunLoopMode 
                dequeue:YES]; 

    [NSApp sendEvent:event]; 
} 

, 로그가 호출됩니다.

그러나 이제 나는이 같은, 그 파견 주위에 랩을 넣어 가정 해 봅시다 :이 코드를 실행하면

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
     NSLog(@"This should appear!"); 
    }); 
    for (;;) 
    { 
     NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask 
              untilDate:[NSDate distantPast] 
               inMode:NSDefaultRunLoopMode 
               dequeue:YES]; 

     [NSApp sendEvent:event]; 
    } 
}); 

, 로그가 실행되지 않습니다. extEventMatchingMask :가 대기열에 포함 된 블록 내부에서 호출되기 때문에 앞으로 전달되는 블록을 처리 할 수 ​​없다는 것을 알 수 있습니다. 그러나 이상한 것은 performSelector를 사용하면 대기열에있는 블록에서도 실행된다는 것입니다.

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
      NSLog(@"This should appear!"); 
     }); 

     [self performSelector:@selector(logAppear) withObject:nil afterDelay:2]; 

     for (;;) 
     { 
      NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask 
               untilDate:[NSDate distantPast] 
                inMode:NSDefaultRunLoopMode 
                dequeue:YES]; 

      [NSApp sendEvent:event]; 
     } 
    }); 

-(void) logAppear { 
    NSLog(@"This should appear!"); 
} 

이 예제를 실행하면 logAppear 메소드가 예상대로 호출됩니다.

간단히 말해 두 번째 케이스가 작동하지 않는 이유와 가능한 경우 디스패치 블록을 실행할 수있는 대기열에있는 블록에서 이벤트 루프를 실행할 수있는 방법을 묻고 싶습니다.

답변

0

몇 가지 실험을 마친 후에 필자가해야 할 일은 해당 이벤트 루프가 대기열에 포함 된 블록 외부에서 실행되었는지 확인하는 것입니다. 루프를 메서드 안에 넣고 performSelector에 의해 호출되는지 확인하면됩니다.

예 :

를 예상대로

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
      NSLog(@"This should appear!"); 
     }); 

     [self performSelector:@selector(logAppear) withObject:nil afterDelay:2]; 

     [self performSelector:@selector(mainLoop) withObject:nil afterDelay:0]; 

    }); 


-(void) mainLoop { 
    for (;;) 
    { 
     NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask 
              untilDate:[NSDate distantPast] 
               inMode:NSDefaultRunLoopMode 
               dequeue:YES]; 

     [NSApp sendEvent:event]; 
    } 
} 

-(void) logAppear { 
    NSLog(@"This should appear!"); 
} 

이 예제를 실행하여 우리는 이제 모두 로그를 얻을