13

如何从命令行应用程序向通知中心发送通知?到目前为止,我的尝试编译并运行,但没有成功通知我。

例子

#import <Cocoa/Cocoa.h>

int main(int argc, const char * argv[]) {
    NSLog(@"Running notifications");

    NSUserNotification *note = [[NSUserNotification alloc] init];
    [note setTitle:@"Test"];
    [note setInformativeText:@"Woot"];

    NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
    [center scheduleNotification: note];

    return 0;
}

然后我编译如下:

clang -framework cocoa /tmp/Notes.m

我得到

 2012-07-29 16:08:35.642 a.out[2430:707] Running notifications

作为输出,但没有通知:(

代码设计是其中的一个因素吗?

4

5 回答 5

19

我发现NSUserNotificationCenter[[NSBundle mainBundle] bundleIdentifier]返回正确的标识符时有效。所以,我写了一些你可以在https://github.com/norio-nomura/usernotification找到的代码

它可以在NSUserNotification没有应用程序包的情况下发送。

于 2013-02-05T01:06:11.613 回答
3

虽然我没有找到任何关于此的特定文档,但我假设您需要成为一个应用程序(捆绑包)来传递通知。请注意,通知中心 UI 始终显示发出通知的应用程序的名称和图标。使用命令行工具是不可能的。

不过,似乎不需要代码签名。

也许您可以编写一个助手应用程序,它只提供通知并从您的命令行工具(例如使用NSDistributedNotificationCenter)与您的助手应用程序进行通信。

于 2012-07-29T20:23:30.467 回答
2

github上已经有一个终端通知器:https ://github.com/julienXX/terminal-notifier

和自述文件说:

它目前被打包为一个应用程序包,因为 NSUserNotification 不能通过“基础工具”工作。雷达://11956694

于 2012-08-13T07:16:25.807 回答
2

我不确定,但也许 scheduleNotification 调用是异步的,您的应用程序在任何事情发生之前就退出了。
尝试添加:

[[NSRunLoop currentRunLoop] run];

到主要的结尾。

于 2012-07-29T20:49:44.797 回答
1

这是我必须做的。请注意,这样的运行循环具有非常小的延迟。有必要查看该通知。

NSUserNotification *n = [[NSUserNotification alloc] init];
n.title = @"My Title";
n.subtitle = @"my subtitle";
n.informativeText = @"some informative text";
[NSUserNotificationCenter.defaultUserNotificationCenter deliverNotification:n];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];

但是,您可能会注意到它显示的是终端图标而不是漂亮的图标。为了解决这个问题,有一种记录不充分的技术。但是,不幸的是,使用这种技术,我不知道如何将它链接到我自己的自定义图标——只链接到已安装的应用程序图标。

  1. 将 Info.plist 文件添加到您的项目中。如果您的项目名为 acme,通常 XCode 会在您的项目中创建一个名为 acme 的黄色文件夹并将您的文件放在那里。因此,在此处添加一个 Info.plist,并且不要忘记在 Info 中将 I 大写。顺便说一句,不用担心将 Info.plist 文件与您的 CLI 应用程序一起分发——它会自动捆绑到二进制文件本身中。

  2. 接下来,打开 Info.plist 并添加一个新项目。它会提示您输入一些默认项目。选择捆绑标识符。现在,在此键的值部分,将其设置为 Applications 文件夹中已安装应用程序的有效捆绑标识符。所以对我来说,我的 LaunchDaemon 是需要发送通知的命令行应用程序,我在 /Applications 文件夹中有一个与之匹配的 GUI 应用程序,名为 /Applications/Acme.app。因此,在 Acme.app 的 Info.plist 文件中,我有我现有的 com.acme.myapp 包标识符。同样,该 GUI 应用程序上已经有一个图标。因此,我将我的 CLI 应用程序的 Info.plist 文件包标识符中的值设置为 com.acme.myapp 以便它使用该图标。现在,您也可以根据需要将其设置为 com.apple.finder,它会抓取 Finder 图标。(顺便提一句,

  3. 现在,进入您的构建设置并使用搜索框并输入“infoplist”。您将看到一个名为“Info.plist 文件”的项目。将其设置为文件的相对文件夹路径。所以,还记得我提到我的项目有一个黄色的“acme”文件夹,而我的 Info.plist 文件就在其中吗?所以,我所要做的就是在第二列(左边说“已解决”)和第三列下输入“acme/Info.plist”。

  4. 现在,在构建设置中,搜索“创建信息”。您将看到一个条目“在二进制文件中创建 Info.plist 部分”。在第二列和第三列中,将其设置为是。

此问题的另一个问题是,当您单击警报时,它会启动命令行应用程序,而不是您可能想要加载的 GUI 应用程序。

于 2016-04-16T10:43:06.420 回答