所以我正在开发我的小 Mac 应用程序,我想用它来控制 Adium。 AppleScript 非常酷:
tell application "Adium"
go away with message "Zoned in for Maths."
end tell
(如果您想知道这应该是什么。为了真正开始学习,我需要创建将更改我的 IM 状态的应用程序,当然......)
我在脚本编辑器中尝试过,它有效,而且我很确定从 Cocoa 应用程序调用 AppleScript 会很简单。
但。
AppleScript 是唯一的方法吗?我不介意使用 AppleScript,但它看起来像是菜鸟编程。
有没有什么方法可以在没有 AppleScript 的情况下以普通 Objective-C 的方式做与上面代码相同的事情?
有人会向我指出相关文档吗?我尝试过谷歌,但好像我什至不知道我在寻找什么。
谢谢!
so I'm working on my little Mac app, and I want control Adium with it. AppleScript is very cool:
tell application "Adium"
go away with message "Zoned in for Maths."
end tell
(If you're wondering what this is supposed to be. In order to actually start studying I need to create application that will change my IM status, of course ... )
I tried it in Script Editor, it worked, and I'm pretty sure that calling AppleScript from Cocoa application is gonna be trivial.
But.
Is AppleScript the only way? I don't mind using AppleScript, but it looks like programming for noobs.
Is there any way to do the same thing as above code does without AppleScript, in plain Objective-C somehow?
Would someone point me to relevant documentation? I tried Google but it was like I don't even know what I'm looking for.
Thanks!
发布评论
评论(3)
Mac OS X 中的进程间通信是通过 Apple Events 来完成的。 AppleScript 是向其他应用程序发送和接收 Apple 事件的一种方法。
因此,您只需要直接构建 Apple 事件并将其从 Objective-C 或任何其他语言发送到其他应用程序。
老实说,如果您只是想更改 Adium 的状态,最简单的方法是使用
NSAppleScript
并从 Objective-C 内部传递您刚刚编写的内容。如果您想做更复杂的事情,脚本Bridge 是必经之路。该机制将 Apple Events 的对象层次结构映射到 Objective-C 的对象层次结构。
如果您认为这仍然是新手的方式,您应该通过
NSAppleEventDescriptor
。好吧,我们中的一些老手认为使用 Objective-C 是一种娘娘腔的方式。如果您这么认为,您应该直接处理称为 AEDesc 等的 C 结构。请参阅 Apple 事件编程指南 和 相应的参考。
不过,我认为使用 OS X 的人都是菜鸟。真正的人使用Linux。
我爸爸会说使用 GUI 的人太被宠坏了。
重点是,你不必关心这是否是新手的方式。重要的是你能否达到你想要的目标。事实上,AppleScript 是一种非常强大的动态语言,但很多人并没有充分认识到它的强大。阅读 AppleScript 语言指南并了解惊讶。
Interprocess communication in Mac OS X is done by something called Apple Events. AppleScript is one way to send and receive Apple Events to other applications.
Therefore, you just need to construct Apple Events directly and send it to the other app, from Objective-C or whatever other language.
Honestly, if you just want to change the status of Adium, it's easiest to use
NSAppleScript
and pass what you just wrote, from inside Objective-C.If you want to do more complicated stuff, Scripting Bridge is the way to go. This mechanism maps Apple Events' object hierarchy to Objective-C's object hierarchy.
If you think that's still a newbie's way, you should directly create Apple Events via
NSAppleEventDescriptor
.Well, some of us old timers think using Objective-C is a sissy's way. If you think so, you should directly deal with C structs called
AEDesc
and such. See Apple Events programming guide and the corresponding reference.However, I think people who use OS X are all noobs. Real people use Linux.
My dad would say people who use GUI are just too spoiled.
The point is, you don't have to care whether it is a newbie's way or not. The important thing is whether you can achieve what you want. In fact, AppleScript is a very powerful, dynamical language, whose power is not well appreciated by many people. Read AppleScript language guide and be surprised.
最简单的方法是使用
NSAppleScript
要获得更强大的访问脚本的方式,请使用 脚本桥。 Scripting Bridge 至少需要 10.5 SDK。您首先需要准备您的应用程序。
sdef
和sdp
命令行实用程序为您想要控制的应用程序生成头文件(请参阅“准备编写代码" 了解详细信息)。之后,您可以使用 Objective-C 向应用程序发送脚本命令。
状态消息是 Adium 的富文本类型(底层是
NSTextStorage
),但它可以从纯文本转换,因此传递NSString
而不是真正的AdiumRichText< /code> 应该可以正常工作。
有几个圈子需要跳过。例如,您不能 直接使用其 ObjC 类在目标应用程序中创建脚本对象;您必须使用
classForScriptingClass:
获取类,然后您可以使用该类正常创建对象(即alloc
和init< /code>,
initWithProperties
&c.)。请注意,其他语言(例如 Python 和 Ruby)也具有脚本绑定。
The simplest way would be to use
NSAppleScript
For a more powerful way of accessing scripting, use Scripting Bridge. Scripting Bridge requires at least the 10.5 SDK. You first need to prepare your app.
sdef
andsdp
command line utilities to generating header files for the applications you wish to control (see "Preparing to Code" for details).After that, you can use Objective-C to send scripting commands to the application.
Status messages are Adium's rich text type (which is
NSTextStorage
under the hood), but it's convertable from plain text, so passing anNSString
rather than a trueAdiumRichText
should work fine.There are a few hoops to jump through. For example, you can't create scripting objects in the target application by using its ObjC classes directly; you must use
classForScriptingClass:
to get the class, which you can then use to create objects as normal (i.e.alloc
andinit
,initWithProperties
&c.).Note that other languages (such as Python and Ruby) also have Scripting bindings.
其他人提到发送完整的 Applescript 或使用脚本桥。第三种选择是使用 Appscript,它也适用于 Python 和 Ruby。在某些方面,它比使用脚本桥更干净(IMO)。而且绝对更容易。尽管在其他方面 Scripting Bridge 更好。它还具有名为 ASTranslate 的应用程序的优势,该应用程序会将大多数 Applescript 调用转换为 Appscript。这是您的小 Applescript 示例的 Appscript。
Others have mentioned sending full Applescript or using the Scripting Bridge. A third choice is to use Appscript which is also available for Python and Ruby. It is a little cleaner (IMO) than using the Scripting Bridge in some ways. And definitely easier. Although in other ways Scripting Bridge is better. It also has the advantage of an application called ASTranslate which will translate most Applescript calls into Appscript. Here's the Appscript for your little Applescript example.