我正在使用Dropbox API for OSX。一切正常,除非我想在以[NSApp runModalForWindow:thisWindow]开头的模态窗口中进行调用;似乎模态循环阻止了 DropboxAPI处理任何东西。 永远不会调用DBRestClient委托方法来响应例如[client loadMetadata:path];这是 - 如果理解正确 - 符合NSApplication文档对此方法所说的内容。问题是: 有没有办法让Dropbox的调用工作在模态窗口内? 我已经看到计时器可以添加到NSModalPanelRunLoopMode中。是否有类似DroboxAPI的东西?
另外:在此显示或任何其他模态窗口显示之前已启动但尚未完成的Dropbox调用会正常进行,还是会被阻止?
是;进一步调查显示任何runModalForWindow甚至显示NSAlert.showModal都将完全阻止DropboxAPI。此外,inplace鼠标处理循环也做同样的事情。 Imo是OSX DropboxAPI的一个主要设计缺陷:它本应该在后台线程上运行。解决这个问题的唯一方法是不启动任何用户任务,这可能涉及阻止Dropbox,而API仍在运行。对于需要Dropbox在后台运行的任何非平凡应用程序而言,这是不可行的。
答案 0 :(得分:1)
NSApplication runModalForWindow的实现确实太苛刻了。
这是更人性化的版本:
void runWindowModal(NSWindow* pnw) {
[pnw retain];
NSApplication* app = [NSApplication sharedApplication];
NSModalSession session = [app beginModalSessionForWindow:pnw];
for( ;; ) {
if ([app runModalSession:session] != NSModalResponseContinue)
break;
NSEvent* e = [app nextEventMatchingMask: NSAnyEventMask
untilDate: [NSDate distantFuture]
inMode: NSDefaultRunLoopMode
dequeue: YES];
if (e != nil)
[app sendEvent: e];
}
[app endModalSession: session];
[pnw release];
}
这将在运行模态循环时启用NSURLConnection和其他回调处理。
答案 1 :(得分:0)
Dropbox支持刚刚确认OSX上的DropboxAPI在主runloop上工作,而且runModalForWindow等也会阻止API。没有解决方法。
答案 2 :(得分:0)
问题更为笼统。所有nsurl连接只能在主runloop上运行。这意味着webview具有相同的问题。并且有一个解决方案。您必须经常创建一个模态会话并在短时间内运行它,并将主线程锁定在一个循环中,直到关闭模态窗口。每次切换回模态会话时,主runloop将完成任何计划任务,包括模态会话中的nsurlconnections。
现在我将向您展示一段代码,但请注意,这是使用Xamarin.Mac库的c#。您应该能够轻松地将其转换为objc。但如果您觉得困难,可以在模态对话框中查找nswebview的解决方案。
//so this is in my NSWindowController - the modal dialog
IntPtr session;
bool running;
public void showDialog ()//this is the method I use to show the dialog
{
running = true;
session = NSApplication.SharedApplication.BeginModalSession (Window);
int resp = (int)NSRunResponse.Continues;
while (running && resp == (int)NSRunResponse.Continues) {
resp = (int)NSApplication.SharedApplication.RunModalSession (session);
NSRunLoop.Current.RunUntil (NSRunLoopMode.Default, NSDate.DistantFuture);
}
NSApplication.SharedApplication.EndModalSession (session);
}
[Export ("windowWillClose:")]
public void WindowWillClose (NSNotification notification)//this is the override of windowWillClose:
{
running = false;
}