【问题标题】:NSApplicationDelegate not getting delayed call after returning NSTerminateLater from ShouldTerminate?从 ShouldTerminate 返回 NSTerminateLater 后,NSApplicationDelegate 没有延迟调用?
【发布时间】: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 确实触发了(并且应用程序没有终止,这很好)。

发生了什么事?

【问题讨论】:

    标签: macos appdelegate appkit


    【解决方案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 下:

    与输入源一样,计时器与运行循环的特定模式相关联。 如果计时器不在运行循环当前监控的模式下,它不会触发,直到您以计时器支持的模式之一运行运行循环。

    【讨论】:

      猜你喜欢
      • 2017-01-19
      • 2023-03-03
      • 2018-04-30
      • 2015-12-15
      • 2011-11-19
      • 1970-01-01
      • 2018-05-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多