命令行工具与Cocoa应用程序交互

7
我有一个Cocoa文档型应用程序(文本编辑器),我希望能够从命令行与它进行交互。
例如,我想将其设置为在命令行上输入git/svn提交消息的编辑器。
假设我使用Foundation创建一个命令行工具,那么我的命令行工具与GUI应用程序通信的最佳方式是什么?
显然,我可以使用标准的打开事件让我的应用程序打开特定文件,但我还需要命令行应用程序等待GUI应用程序完成文档操作(用户关闭编辑器窗口)后再退出(类似于TextMate的命令行工具中的mate -w file.txt或其他各种Mac文本编辑器的等效工具)。
TextMate 2 使用套接字文件。这是最好的方法吗?如果可能的话,我想使用更高级别的东西,例如NSDistributedNotificationCenter

1
你可以使用命名管道吗?或者使用套接字/端口? - Shark
@Shark TextMate 2使用套接字,但它似乎有很多相当复杂的代码,所以我把它当作最后的手段。我不确定命名管道...我该怎么做?如果GUI应用程序在执行命令行工具时已经运行,那么这是否有效?如果我遇到NSDistributedNotificationCenter的问题,我会研究一下,除非您想发布一个解释它如何工作的答案。 - Abhi Beckert
http://en.wikipedia.org/wiki/Named_pipe 此外,不要害怕套接字,因为网上有大量示例代码。 - Shark
3个回答

2
如果你看一下iTerm的源代码,可以在这里找到:

svn co https://iterm.svn.sourceforge.net/svnroot/iterm iterm

你会看到他们是如何实现的。他们使用了Growl通知。Growl是一个全面的通知框架,允许你真正控制发生的事情并正确地响应所有内容。你可以在这里找到更多关于Growl的信息:

http://growl.info/


2

NSDistributedNotificationCenter可能会很好地工作,如果这是您喜欢的抽象级别。它的接口与NSNotificationCenter类似。关于NSDistributedNotificationCenter

  • 它仅限于plist类型
  • 允许删除通知
  • 它很昂贵
  • 延迟可能是不可预测的
  • 沙盒应用程序无法使用userInfo:参数

如果您想要传输大量信息,或者想要更健壮/可预测的内容,您可能会发现套接字更可取。


性能不是问题,我可能只在典型使用情况下发送5或10个通知。有人知道通知被丢弃的频率吗?“不可预测”的延迟的最坏情况是什么?这些可能会成为交易破坏者,但也许只有在向系统发送数千条消息时才会发生?我只需要发送一条消息,并且非常不频繁。也许GUI应用程序可以等待命令行发送确认通知,并在等待2或3秒后向用户显示错误。 - Abhi Beckert
@AbhiBeckert 关于频率:这个问题实际上无法回答,因为当消息队列填满时通知会被丢弃,所以......最终取决于许多因素,这些因素在用户之间并不一致。每天10次应该没有问题。如果有问题,您可以进入抽象层NSDistributedNotificationCenter使用NSConection+NSDistantObject直接使用。或者您可以使用NSMachPort。延迟是不可预测的,因为它将取决于侦听器对排队通知的响应速度,这些通知可能会添加到您的运行循环中。(cont) - justin
@AbhiBeckert,我实际上在OS X.4时代使用了NSDistributedNotifcationCenter进行高密度消息传递(高密度:在压力测试期间)。基本上,我有一个系统,其中包含系统插件和一个应用程序,该应用程序将呈现系统范围任务的状态(活动任务计数,结果消息)。测试工作量高达每秒几百个活动、连续的任务。我不记得在那种情况下出现丢失消息的问题。但是,所有这些都通过全局消息队列进行,因此它并不值很多,因为另一个用户的系统可能会有很大的差异 :) - justin
1
@AbhiBeckert 所以我的简短结论就是,只需从 NSDistributedNotifcationCenter 开始,如果你注意到任何问题,再切换到更低级别的抽象层。只需将应用程序通信与程序的其余部分分离,如果必要(我认为这很不可能),切换到更低级别的抽象层应该很容易。 - justin

0

您可以在项目信息面板中添加URL方案到您的应用程序。

当任何人尝试访问URL yourscheme://info/for/your/app 时,如果应用程序未启动,则会启动您的应用程序并传递参数。

以下是您的应用程序中处理URL的代码:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{

// ...

    [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleAppleEvent:withReplyEvent:)
                                                     forEventClass:kInternetEventClass andEventID:kAEGetURL];
}

- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
    NSString *urlString = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
// .. process your url
}

一个命令行工具能否注册自己的URL方案?我需要在命令行工具和GUI应用程序之间进行双向通信。 - Abhi Beckert
我认为你无法在命令行工具和GUI应用程序之间进行通信。您可以尝试通过在info.plist中将“Application is background only”设置为Yes来使您的应用程序成为“仅后台”。在这种情况下,该应用程序将支持URL方案和NSDistributedNotificationCenter。 - Remizorrr
我的任务的整个目的是允许UNIX shell命令(例如git)与GUI文本编辑器进行交互。这绝对是可行的,大多数Mac文本编辑器都可以做到。 - Abhi Beckert
你可以使用FSEvents来跟踪文件夹的更改并将文件放在那里,但我认为这不是最好的解决方案。 - Remizorrr
是的,我以前使用过FSEvents。我希望GUI应用程序在文本编辑器窗口关闭时通知命令行应用程序。但是没有相应的FSEvent。 - Abhi Beckert
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接