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

时间:2011-09-11 17:58:44

标签: objective-c cocoa 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;          
}

这是设备控制器代码:

- (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}}再次被召唤?我认为必须。有没有更好的方法在完成处理程序中退出应用程序?

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;          
}