处理 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)
循环。通常的方法是注册各种事件,然后等待它们发生。这就是 运行 循环的用途。但是如果你必须管理自己的循环(你通常不应该,但如果你必须),那么你需要将它从主队列中移出。
我想在任何应用程序关闭时执行我的方法。我的代码是:
@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)
循环。通常的方法是注册各种事件,然后等待它们发生。这就是 运行 循环的用途。但是如果你必须管理自己的循环(你通常不应该,但如果你必须),那么你需要将它从主队列中移出。