这是一个奇怪的。我的应用程序将关闭消息发送到控制硬件设备的对象,并将完成 block 作为参数。关闭消息返回一个 BOOL,这取决于它是否能够立即完成关闭。所以 YES 表示它现在完成,NO 表示它将在稍后完成时调用完成处理程序。
这是主要的 Controller 代码:
- (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;
}
这是设备 Controller 代码:
- (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
因此在完成 block 运行后,我最终回到设备对象的 shutdownWithCompletionHandler:
方法中。为什么?
编辑:嗯。 [[NSRunningApplication currentApplication] terminate];
是否导致
applicationShouldTerminate:
再次调用?我认为必须的。有没有更好的方法在完成处理程序中退出应用程序?
最佳答案
既然您已经找到问题的根本原因(调用 terminate
会导致 applicationShouldTerminate:
),下面是避免问题的方法。
不是取消终止,而是在稍后关闭时返回 NSTerminateLater
。然后,您的完成 block 应调用 [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;
}
关于Objective-C 完成 block 导致额外的方法调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7380210/