我遇到一个文档文件依赖于另一个外部媒体文件的链接的情况。打开文档后,我检查参考媒体文件是否可用,如果没有,则会提示用户查找它。

由于在基于文档的应用程序中将NSOpenPanel显示为表格非常合理,因此我想这样做,但是阻止当前线程至关重要,因此在选择新的媒体文件之前,无法调用任何后续代码。

我找不到在阻止当前线程时在文档窗口上以表格形式显示此NSOpenPanel的方法。只有[NSOpenPanel runModal]可以满足我的需要,但是显示为常规对话框而不是工作表。

看来这应该是可能的...

最佳答案

警告:我假设您使用的是沙盒,所以NSOpenPanelNSSavePanel是基于伏都教的-它们的行为会因OS点释放,月相,房屋中是否存在蓝纹奶酪等而异。而让他们正常表现可能需要很大的耐心。 (请参见this question for one person's recent pain。)是的,我在开玩笑-有点-但是您已经被警告过。

还在?

众所周知,与以下两个代码相似的代码可以在某个时间点运行,即满月和午夜之后的主要秒数。

刚输入答案的所有代码,都希望输入错误。

第一:

+ (NSInteger) myRunModal:(NSOpenPanel *)myPanel
        asSheetForWindow:(NSWindow *)myWindow
{
   [myPanel beginSheetModalForWindow:myWindow
                   completionHandler:^(NSInteger result)
                                     {
                                        [NSApp stopModalWithCode:result];
                                     }
   ];
   return [NSApp runModalForWindow:myWindow];
}


在调用beginSheetModalForWindow:之后,您的线程进入一个模态循环,仅处理窗口事件。当完成处理程序被调用时,它执行并退出该模式循环,并返回结果。

无论您做什么,都不要尝试将其作为类别添加到NSOpen / SavePanel类中。这样会导致疯狂。记住他们是巫毒教徒,不要以任何方式直接与他们混在一起。

第二:

使用信号量,一方面,这似乎很明显,另一方面,僵局立即浮现在脑海中……

+ (void) myRunModal:(NSOpenPanel *)myPanel
   asSheetForWindow:(NSWindow *)myWindow
  completionHandler:(void (^)(NSInteger))myHandler
{
   // Use a semaphore to block thread till sheet is done
   dispatch_semaphore_t sema = dispatch_semaphore_create(0);
   [myPanel beginSheetModalForWindow:myWindow
                   completionHandler:^(NSInteger result)
                                     {
                                        myHandler(result);
                                        // Unblock caller
                                        dispatch_semaphore_signal(sema);
                                     }
   ];
   // Block until sheet completes
   dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}


您的线程在这里等待信号量发出信号。如果系统要在同一线程上执行处理程序,则将导致死锁。会尝试吗?也许。

但是,如果可以安排代码使需要调用NSOpenPanel的代码在线程上运行,则安排beginSheetModalForWindow:在主线程上运行,而dispatch_semaphore_wait在线程上运行,那么可以采用一种可靠的解决方案应该掌握在你手中。

第三:

是的,我只说了两个,第三个选择是甚至不要尝试。

高温超导

关于cocoa - 将NSOpenPanel同步显示为工作表,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28478020/

10-10 20:30