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

标签 objective-c cocoa objective-c-blocks

这是一个奇怪的。我的应用程序将关闭消息发送到控制硬件设备的对象,并将完成 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/

相关文章:

ios - UIButton 未激活

objective-c - 向所有用户发送推送通知

iphone - 核心数据 : Find the property of NSEntity Objects in NSMutableSet

objective-c - NSTableView + 删除键

iphone - 将 block 与 NSOperation 一起使用

ios - Xcode 构建过程卡在 "Copying swiftdocs"

ios - 使用addObserverForName时保留循环:object:queue:usingBlock:

cocoa - 如何设置与 NSButton 上的 Enter/Return 键等效的 Key?

objective-c - 将对象分配给 block 外的变量

objective-c - 如何在 Objective-C 的属性中存储 block ?