Cocoa 将NSOpenPanel同步显示为工作表
我遇到一种情况,文档文件依赖于指向另一个外部媒体文件的链接。打开文档时,我会检查引用的媒体文件是否可用,如果不可用,则会提示用户查找该文件 由于在基于文档的应用程序中将NSOpenPanel显示为工作表是非常有意义的,因此我想这样做,但当前线程被阻止是至关重要的,因此在选择新媒体文件之前,无法调用后续代码 在阻止当前线程时,我找不到在文档窗口中将此NSOpenPanel显示为工作表的方法。只有Cocoa 将NSOpenPanel同步显示为工作表,cocoa,nsopenpanel,Cocoa,Nsopenpanel,我遇到一种情况,文档文件依赖于指向另一个外部媒体文件的链接。打开文档时,我会检查引用的媒体文件是否可用,如果不可用,则会提示用户查找该文件 由于在基于文档的应用程序中将NSOpenPanel显示为工作表是非常有意义的,因此我想这样做,但当前线程被阻止是至关重要的,因此在选择新媒体文件之前,无法调用后续代码 在阻止当前线程时,我找不到在文档窗口中将此NSOpenPanel显示为工作表的方法。只有[NSOpenPanel runModal]可以满足我的需要,但它显示为常规对话框而不是工作表 这似乎在
[NSOpenPanel runModal]
可以满足我的需要,但它显示为常规对话框而不是工作表
这似乎在某种程度上是可能的…警告:我假设您正在使用沙箱,因此
NSOpenPanel
&NSSavePanel
基于巫毒-他们的行为往往会因操作系统点释放、月亮相位、房子里是否有蓝色奶酪而有所不同,让他们表现正常需要很大的耐心。(见。)是的,我是在开玩笑——有一点——但是你已经被警告过了
还在这儿吗
已知类似于以下两种代码的代码在某个时间点工作,即满月和午夜后的质数秒
所有代码都只是输入到答案中,除了打字错误
第一:
+ (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\u semaphore\u wait
在主线程上运行,那么您应该掌握一个健壮的解决方案
第三:
是的,我只说了两个,第三个选项是不要尝试
HTH在NSProgressIndicator上有一个属性,表示天气与否是不确定的。为了显示进度,您必须将其设置为“否”我完全理解您的回答的深度,但由于这是一个罕见的事件,我认为我将接受UI不一致性,并选择您的选项3!