应用程序应该终止和NSURLConnection

3
在我的Mac OS X应用程序中,我正在将数据库推送到Dropbox(一种同步方式)。当用户退出应用程序时,我希望在退出之前上传数据库。因此,我实现了applicationShouldTerminate:方法,在其中调用同步方法并返回NSTerminateLater。但是,底层的NSURLConnection根本不起作用-没有调用委托方法,什么也没有发生。所有的上传代码都可以从其他地方正常工作,即使我从applicationShouldTerminate:方法中返回NSTerminateCancel时也是如此。如果这个问题遇到的话,这是在Mac OS Lion 10.7 / XCode 4.6上发生的。
那么,有什么意见吗?返回NSTerminateLater是否会改变运行循环的某些东西或其他地方?

我已经知道可以返回NSTerminateCancel,完成我的任务,在应用程序中设置一些标志并调用NSApp的终止。 - Nickolay Olshevsky
1个回答

3
文档说明,返回 NSTerminateLater 后,应用程序将在 NSModalPanelRunLoopMode 模式下运行主运行循环,直到您调用 replyToApplicationShouldTerminate:
默认情况下,NSURLConnection 对象不会被安排在 NSModalPanelRunLoopMode 模式下(仅在 NSDefaultRunLoopMode 下)。因此,连接正在工作,但委托消息未传递,因为主运行循环需要处于 NSDefaultRunLoopMode 模式。
这允许Cocoa在显示模态对话框(NSModalPanelRunLoopMode)或跟踪鼠标拖动事件(NSEventTrackingRunLoopMode)时暂停异步任务的观察。尽管在某些情况下可能有正当理由,但人们倾向于认为模态界面是不好的,因为它们会产生干扰、挫败和模式错误(因此出现了您的问题)。
因此,为了使您的NSURLConnection正确执行,您需要在NSDefaultRunLoopModeNSModalPanelRunLoopMode模式中安排它。这可以通过NSRunLoopCommonModes实现,该别名用于已声明为“常见”(即Cocoa使用的所有模式)的所有运行循环模式。
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
[connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[connection start];

感谢您提供详细的解释。不幸的是,快速更改Dropbox SDK中提到的内容并不能解决问题。可能在他们那边情况会更加复杂,或者我没有改变他们创建NSURLConnection的所有位置。无论如何,主要的想法是理解发生了什么。 - Nickolay Olshevsky
我正在将我的连接安排在currentRunLoop的公共模式中,但在返回NSTerminateLater后仍然没有收到委托回调。当连接在终止被调用之前或之后启动时,会有什么区别吗? - Julian F. Weinert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接