处理 objective c 内关闭的任何应用程序

Handle any application closing in objective c

我想在任何应用程序关闭时执行我的方法。我的代码是:

@interface FO: NSObject
- (void)applicationKilled:(NSNotification*)notification;
- (void)appDidLaunch:(NSNotification*)notification; 
@end

@implementation FO
- (void)applicationKilled:(NSNotification*)notification {
    NSLog(@"success");
}

- (void)appDidLaunch:(NSNotification*)notification {
    NSLog(@"app info: %@", [notification userInfo]);
}  
@end

@implementation Main:NSObject
FO fo; 
NSString * filePath = "...MyPath";
NSString * application = "..MyApplication";
 int main(int argc, const char * argv[]) {
    fo = [[FO alloc]init];
    [Main MyMethod];
    while(1==1) {
      ...some code;
        }
        return 0;
 }

+(void) MyMethod {
    center = [[NSWorkspace sharedWorkspace] notificationCenter];
    [center addObserver:fo selector:@selector(appDidLaunch:) name:NSWorkspaceDidLaunchApplicationNotification object:nil];
    [center addObserver:fo selector:@selector(applicationKilled:) name:NSWorkspaceDidTerminateApplicationNotification
                                     object:nil];         
    [[NSWorkspace sharedWorkspace] openFile:filePath withApplication:application]; }
@end

但是,appDidLaunch 方法没有触发,即使我将在 finder 中打开另一个应用程序。 applicationKilled 方法也永远不会触发。 当我执行以下代码时

[center postNotificationName:NSWorkspaceDidLaunchApplicationNotification
     object:self];

appDidLaunch 方法正在启动。哪里会出问题?是否应在每次打开或关闭某些应用程序时触发此方法?

假设您使用的是 ARC 并且还猜测您提供的信息似乎不完整:

在您更新的问题中,您显示 fo 声明为 MyMethod 的局部变量。 addObserver:selector:name:object: 方法 而不是 保持对观察者的强引用。在 MyMethod returns 本地 fo 对象将被回收后,您现在没有观察者可以调用方法。

但是,虽然上面可以解释为什么你的代码不起作用,但不能解释为什么你的应用程序没有崩溃——而且你没有报告它崩溃. 运行 您在上面提供的代码导致应用程序崩溃。所以看来您错过了一些信息,或者至少没有报告崩溃。

猜二

您没有 运行 循环

框架的许多部分都依赖于 运行 循环,该循环将传入事件分派给适当的处理程序 - 只需在 Xcode 的帮助中键入 "run loop"。如果您使用 Xcode 的 "Cocoa Application" 模板创建标准应用程序,则 main.m.

中的代码会为您创建 运行 循环

当应用程序启动和停止时,OS X 产生的事件由 运行 循环分派到框架处理程序,框架处理程序产生相应的通知。如果没有 运行 循环,这些系统事件将不会被处理,因此不会有通知。

你有:

int main(int argc, const char * argv[])
{
   fo = [[FO alloc]init];
   [Main MyMethod];
   while(1==1)
   {
      ...some code;
   }
   return 0;
}

所以除非“...一些代码”创建一个 运行 循环系统事件将不会被处理。

使用标准 "Cocoa Application" 模板编写您的项目,例如,在 applicationDidFinishLaunching:.

中调用设置通知处理程序

HTH

CRD 走在正确的轨道上。您绝对必须有一个 运行 循环才能接收此通知。例如:

@implementation Main : NSObject

- (void)applicationDidFinishLaunching:(NSApplication *)app {
    [Main MyMethod];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
        // ... The rest of your program ...
    });
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MyDelegate *delegate = [Main new];
        [[NSApplication sharedApplication] setDelegate:delegate];
        [NSApp run];
    }
    return 0;
}

我已将 "the rest of your program" 放入 dispatch_async 中,因为您不能阻塞主线程。 Mac 应用程序通常的工作方式不是大 while (YES) 循环。通常的方法是注册各种事件,然后等待它们发生。这就是 运行 循环的用途。但是如果你必须管理自己的循环(你通常不应该,但如果你必须),那么你需要将它从主队列中移出。