这是一个奇怪的。我的应用程序向控制硬件设备的对象发送关闭消息,并以完成块作为参数。关闭消息返回BOOL,具体取决于它是否能够立即完成关闭。所以YES意味着它现在已经完成,NO表示它将在稍后完成时调用完成处理程序。
这是主控制器代码:
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
BOOL shutdownNow = [theStoker shutdownWithCompletionHandler:^(void)
{
NSLog(@"applicationShouldTerminate: completionBlock");
[[NSRunningApplication currentApplication] terminate];
}];
if (!shutdownNow)
{
NSLog(@"applicationShouldTerminate: waiting for shutdown");
return NSTerminateCancel;
}
return NSTerminateNow;
}
这是设备控制器代码:
- (BOOL)shutdownWithCompletionHandler:(void (^)(void))handler
{
if (busy)
{
self.completionBlock = handler;
[self stopDevice];
NSLog(@"shutdownWithCompletionHandler: Wait for reset");
return NO;
}
NSLog(@"Stoker: shutdownWithCompletionHandler: shutdown now");
return YES;
}
奇怪的部分是关闭消息要发送两次。这些是NSLog消息:
shutdownWithCompletionHandler: Wait for reset
applicationShouldTerminate: waiting for reset
applicationShouldTerminate: completionBlock
shutdownWithCompletionHandler: shutdown now
因此,在完成块运行后,我最终返回设备对象的shutdownWithCompletionHandler:
方法。为什么呢?
[[NSRunningApplication currentApplication] terminate];
导致了吗applicationShouldTerminate:
{{1}}再次被召唤?我认为必须。有没有更好的方法在完成处理程序中退出应用程序?
答案 0 :(得分:5)
由于您已找到问题的根本原因(调用terminate
导致applicationShouldTerminate:
),因此以下是如何避免此问题。
取代取消终止,在稍后关闭时返回NSTerminateLater
。然后,您的完成块应调用[NSApp replyToApplicationShouldTerminate:YES]
来触发终止,而无需再次调用applicationShouldTerminate:
。
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
BOOL shutdownNow = [theStoker shutdownWithCompletionHandler:^(void) {
NSLog(@"applicationShouldTerminate: completionBlock");
[NSApp replyToApplicationShouldTerminate:YES];
}];
if (!shutdownNow) {
NSLog(@"applicationShouldTerminate: waiting for shutdown");
return NSTerminateLater;
}
return NSTerminateNow;
}