Objective-C完成块导致额外的方法调用?

Fly*_*ver 4 cocoa objective-c objective-c-blocks

这是一个奇怪的.我的应用程序向控制硬件设备的对象发送关闭消息,并以完成块作为参数.关闭消息返回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;          
}
Run Code Online (Sandbox Code Playgroud)

这是设备控制器代码:

- (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;
}
Run Code Online (Sandbox Code Playgroud)

奇怪的部分是关闭消息要发送两次.这些是NSLog消息:

shutdownWithCompletionHandler: Wait for reset
applicationShouldTerminate: waiting for reset
applicationShouldTerminate: completionBlock
shutdownWithCompletionHandler: shutdown now
Run Code Online (Sandbox Code Playgroud)

所以在完成块运行之后,我最终回到了设备对象的shutdownWithCompletionHandler:方法中.为什么?

编辑:嗯.[[NSRunningApplication currentApplication] terminate];导致applicationShouldTerminate:再次被召唤的原因是 什么?我认为必须.有没有更好的方法在完成处理程序中退出应用程序?

ugh*_*fhw 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;          
}
Run Code Online (Sandbox Code Playgroud)