2014-04-08 9 views
5

다음 코드가 작동하는 이유는 무엇입니까? NSOpenPanel을 사용하여 파일을 선택하고 Emacs.app에서 열어 보는 작은 코코아 프로그램입니다. 시작 디렉토리를 인수로하여 명령 행에서 실행할 수 있습니다.NSApplication 또는 NSRunLoop 호출없이 Cocoa GUI 클래스가 실행되는 방식

NSApplication 또는 NSRunLoop을 호출하지 않고 NSOpenPanel을 실행하는 방법은 무엇입니까? NSApplication 또는 NSRunLoop을 명시 적으로 시작하지 않는 Cocoa 프로그램의 제한 사항은 무엇입니까? 나는 그 중 하나가 있다고 생각했을 것이다. 어떤 종류의 GUI도 사용할 수 없다. 아마도 NSOpenPanel을 호출하면 NSRunLoop을 호출하는 대체 코드가 호출됩니다. 나는 [NSApplication alloc] 및 + [NSRunLoop alloc]에 중단 점을 넣었지만 트리거되지 않았습니다.

main.m: 

#import <Cocoa/Cocoa.h> 

NSString *selectFileWithStartPath(NSString *path) { 
    NSString *answer = nil; 
    NSOpenPanel* panel = [NSOpenPanel openPanel]; 
    panel.allowsMultipleSelection = NO; 
    panel.canChooseFiles = YES; 
    panel.canChooseDirectories = NO; 
    panel.resolvesAliases = YES; 
    if([panel runModalForDirectory:path file:nil] == NSOKButton) 
    answer = [[[panel URLs] objectAtIndex:0] path]; 
    return answer; 
} 

int main(int argc, const char * argv[]) { 
    NSString *startPath = argc > 1 ? [NSString stringWithUTF8String:argv[1]] : @"/Users/Me/Docs"; 
    printf("%s\n", argv[1]); 
    BOOL isDir; 
    if([[NSFileManager defaultManager] fileExistsAtPath:startPath isDirectory:&isDir] && isDir) { 
    system([[NSString stringWithFormat:@"find %@ -name \\*~ -exec rm {} \\;", startPath] UTF8String]); 
    NSString *file = selectFileWithStartPath(startPath); 
    if(file) [[NSWorkspace sharedWorkspace] openFile:file withApplication:@"Emacs.app"]; 
    } 
} 

답변

5

runModalForDirectory:file:types:은 자체 이벤트 루프를 생성하고 실행합니다. 문서에서 :

표시 패널은 사용자가 확인 또는 취소 중 하나를 클릭 할 때 종료 모달 이벤트 루프를 시작합니다.

당신은 "열기"대화 상자가 를 활성화되어있는 동안 또한 프로그램을 일시 정지하는 경우 그 볼 디버거 콘솔에서 스택 역 추적을 인쇄 할 수 있습니다 : 당신이 프레임 # 11에서 볼 수 있듯이

frame #0: 0x00007fff8b855a1a libsystem_kernel.dylib`mach_msg_trap + 10 
frame #1: 0x00007fff8b854d18 libsystem_kernel.dylib`mach_msg + 64 
frame #2: 0x00007fff8549f155 CoreFoundation`__CFRunLoopServiceMachPort + 181 
frame #3: 0x00007fff8549e779 CoreFoundation`__CFRunLoopRun + 1161 
frame #4: 0x00007fff8549e0b5 CoreFoundation`CFRunLoopRunSpecific + 309 
frame #5: 0x00007fff88381a0d HIToolbox`RunCurrentEventLoopInMode + 226 
frame #6: 0x00007fff883817b7 HIToolbox`ReceiveNextEventCommon + 479 
frame #7: 0x00007fff883815bc HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter + 65 
frame #8: 0x00007fff838ca3de AppKit`_DPSNextEvent + 1434 
frame #9: 0x00007fff838c9a2b AppKit`-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 122 
frame #10: 0x00007fff83c28e2e AppKit`-[NSApplication _realDoModalLoop:peek:] + 642 
frame #11: 0x00007fff83c2754e AppKit`-[NSApplication runModalForWindow:] + 117 
frame #12: 0x00007fff83ef5d0b AppKit`-[NSSavePanel runModal] + 276 
frame #13: 0x0000000100000c61 xxx`selectFileWithStartPath(path=0x00000001000010b8) + 225 at main.m:18 
frame #14: 0x0000000100000e0d xxx`main(argc=1, argv=0x00007fff5fbff9c0) + 189 at main.m:26 

을 , -[NSApplication runModalForWindow:]은 "열기"대화 상자의 모달 이벤트 루프를 실행하는 데 사용됩니다.

+0

예, 알 수 있습니다. 빠른 응답에 감사드립니다. 방금 깨달은 한가지는 오래된 고전적인 main.m이 [NSApplication alloc]이 아니라 [NSApplication sharedApplication]을 호출한다는 것입니다. runModalForWindow에 대한 호출이 Apple 라이브러리에서 싱글 톤 [NSApplication sharedApplication]을 인스턴스화하여 앞당겨 졌을 것으로 추측합니다. – Colin