【发布时间】:2016-01-28 22:06:33
【问题描述】:
经过几天的调试,我仍然无法弄清楚为什么 NSOpenPanel(或 NSSavePanel,就此而言)在第一次访问文件夹后会显示一个空文件列表。它这样做似乎是随机的,即有时会显示文件(可能是因为它们被缓存),但看起来,如果第一次访问文件夹或卷,则不会。如果用户返回并再次访问同一个文件夹,所有文件都会显示出来。
NSOpenPanel 根据需要在主线程上模态运行。有另一个线程在运行。降低其他线程的优先级并没有帮助。暂停它不是一种选择。
我怀疑 OS X 在完成文件检索后会向面板(或应用程序)发送一些延迟事件(这可能需要一段时间)。无论出于何种原因,我的 NSOpenPanel 似乎都错过了它。
那是什么活动?我怎样才能防止它丢失?
编辑:NSOpenPanel 由委托对象在主线程上构建和打开。面板从带有[delegate performSelectorOnMainThread: @selector(runPanel) withObject: nil waitUntilDone: NO] 的辅助线程打开。所以辅助线程会立即继续工作并轮询委托,直到面板完成,以获取结果。
(是这样的,因为辅助线程运行的模拟需要在用户提供输入的同时继续进行)
编辑:NSOpenPanel 有一个附属视图。
编辑:面板运行时在主线程上堆栈帧。
-[SavePanelDelegate runPanel] + 185
-[NSObject performSelector:withObject:] + 70
__NSThreadPerformPerform + 318
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
__CFRunLoopDoSources0 + 235
__CFRunLoopRun + 1022
CFRunLoopRunSpecific + 394
CFRunLoopRunInMode + 123
RunCurrentEventLoopInMode + 259
ReceiveNextEventCommon + 526
_BlockUntilNextEventMatchingListInModeWithFilter + 92
_DPSNextEvent + 1602
-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 119
-[NSApplication run] + 727
NSApplicationMain + 1165
main + 99
今天我在重现问题时遇到了困难。直到一个小时左右并重新启动 Mac 后,它才再次发生。很奇怪。
【问题讨论】:
-
将
NSLog(@"%@", [NSThread callStackSymbols]);放在-runPanel方法的开头附近并显示输出。另外,当这种情况发生时,还有什么其他记录到控制台吗?不妨也显示您的-runPanel方法的代码。 -
堆栈框架或控制台上没有任何可疑之处。看到它已添加到帖子中。
-
更改文件选择后,有一个临时线程
TThumbnailExtractorThread与TConditionVariable::WaitWithTimeout()相关。它可能正在收集要显示的文件图标。一段时间后,线程消失了。由于没有记录错误,因此很难评估这是否与此处相关。
标签: objective-c macos cocoa nsopenpanel