从 ShouldTerminate 返回 NSTerminateLater 后,NSApplicationDelegate 没有延迟调用?
Posted
技术标签:
【中文标题】从 ShouldTerminate 返回 NSTerminateLater 后,NSApplicationDelegate 没有延迟调用?【英文标题】:NSApplicationDelegate not getting delayed call after returning NSTerminateLater from ShouldTerminate? 【发布时间】:2018-04-01 22:29:44 【问题描述】:我在 Xcode 中创建了一个 Mac 应用程序。我所做的唯一代码更改是在应用程序委托中。现在它的全部内容如下:
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
- (void) readyToTerminate: (id) sender
NSLog(@"Ready to terminate");
[NSApplication.sharedApplication replyToApplicationShouldTerminate:YES];
- (NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication *)sender
[self performSelector:@selector(readyToTerminate:) withObject:self afterDelay:1.0];
NSLog(@"Later please");
return NSTerminateLater;
- (void)applicationWillTerminate:(NSNotification *)aNotification
NSLog(@"Terminating");
@end
当我运行应用程序时,我确实看到了一个窗口。然后我按命令-Q 终止。输出是:
2018-04-01 17:20:03.110563-0500 TerminateThisApp[3336:364401] Unknown Window
class (null) in Interface Builder file,
creating generic Window instead
2018-04-01 17:20:06.929175-0500 TerminateThisApp[3336:364401] Later please
所以 readyToTerminate: 没有被调用。为什么会这样?我不明白。
为了它的价值,我尝试了一个同样没有结果的 NSTimer。我还尝试以与 didFinishLaunching 相同的方式调用 readyToTerminate。在这种情况下,readyToTerminate 确实触发了(并且应用程序没有终止,这很好)。
发生了什么事?
【问题讨论】:
【参考方案1】:我刚刚使用您的代码在 Xcode 9.3 上构建了一个快速的 macOS 应用程序,并注意到选择器引发了启动服务异常(当您在调试器中单步执行代码时,请增加您的时间以便清楚地看到它)。
如果您查看Console
应用程序并按您的应用程序名称进行过滤(例如,我使用了SO-49603218
),您是否会看到这样的条目:
default 09:44:00.031347 +1000 SO-49603218 LSExceptions shared instance invalidated for timeout.
default 09:44:55.906555 +1000 SO-49603218 Later please
我认为应用程序引用计时器所指的可能是 self
正在失效。这可能与您回复 NSTerminateLater
时将运行循环切换到 NSModalPanelRunLoopMode
有关
如果您更改为NSTerminateCancel
,那么您的readyToTerminate:
方法将被调用。
default 09:55:28.851246 +1000 SO-49603218 Later please
default 09:55:28.864566 +1000 SO-49603218 LSExceptions shared instance invalidated for timeout.
default 09:55:29.851891 +1000 SO-49603218 Ready to terminate
注意LSException
仍然被抛出 ?
我认为在阅读了有关Anatomy of a Run Loop documentation 的更多信息后,问题是performSelector:
调用是在NSDefaultRunLoopMode
上进行的,因此在您返回该运行模式之前不会调用它。从文档中,在 Timer Sources 下:
与输入源一样,计时器与运行循环的特定模式相关联。 如果计时器不在运行循环当前监控的模式下,它不会触发,直到您以计时器支持的模式之一运行运行循环。
【讨论】:
以上是关于从 ShouldTerminate 返回 NSTerminateLater 后,NSApplicationDelegate 没有延迟调用?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 xib 文件在单元格中 rtl UITextField?
从 main 返回零是不是必要,从 main 的返回值如何有用?