【问题标题】:AppleScript is cool. Can I do the same thing in plain Objective-C?AppleScript 很酷。我可以在普通的 Objective-C 中做同样的事情吗?
【发布时间】:2010-12-14 05:33:35
【问题描述】:

所以我正在开发我的小型 Mac 应用程序,我想用它来控制 Adium。 AppleScript 很酷:

tell application "Adium"
    go away with message "Zoned in for Maths."
end tell

(如果您想知道这应该是什么。为了真正开始学习,我需要创建可以改变我的 IM 状态的应用程序,当然......)

我在脚本编辑器中尝试过,它成功了,而且我很确定从 Cocoa 应用程序调用 AppleScript 会很简单。

但是。

AppleScript 是唯一的方法吗?我不介意使用 AppleScript,但它看起来像是为新手编程。

有没有什么方法可以在没有 AppleScript 的情况下以某种方式在纯 Objective-C 中执行与上述代码相同的操作?

有人能指点我相关的文件吗?我试过谷歌,但我什至不知道我在找什么。

谢谢!

【问题讨论】:

    标签: objective-c applescript


    【解决方案1】:

    Mac OS X 中的进程间通信由称为 Apple 事件的东西完成。 AppleScript 是向其他应用程序发送和接收 Apple 事件的一种方式。

    因此,您只需要直接构建 Apple 事件并将其从 Objective-C 或任何其他语言发送到其他应用程序。

    老实说,如果您只想更改 Adium 的状态,最简单的方法是使用 NSAppleScript 并从 Objective-C 内部传递您刚刚编写的内容。

    如果您想做更复杂的事情,Scripting Bridge 是您的最佳选择。这种机制将 Apple Events 的对象层次结构映射到 Objective-C 的对象层次结构。

    如果您认为这仍然是新手的方式,您应该直接通过NSAppleEventDescriptor 创建 Apple Events。

    嗯,我们中的一些老手认为使用 Objective-C 是娘娘腔的方式。如果你这么认为,你应该直接处理名为AEDesc 之类的C 结构。请参阅Apple Events programming guide 和the corresponding reference。

    不过,我认为使用 OS X 的人都是菜鸟。真实的人使用 Linux。

    我爸爸会说使用 GUI 的人太宠坏了。

    关键是,你不必在意这是否是新手的方式。重要的是你能不能达到你想要的。事实上,AppleScript 是一种非常强大的动态语言,它的强大功能并没有被很多人所欣赏。阅读AppleScript language guide 并感到惊讶。

    【讨论】:

    • 这是一个了不起的答案。我并不是那种以使用 GUI 为耻的黑客爱好者。也许我是这么说的。实际上,我不想使用 AppleScript 的原因是因为它隐藏了我感兴趣的东西。它隐藏了它内部的工作原理,这就是我很好奇的地方。感谢您的链接,我想这正是我想要的!
    • AppleScript 实际上是一种非常非常强大的语言。只是大多数人没有注意到。阅读developer.apple.com/library/mac/#documentation/AppleScript/…。
    • AppleScript 被编译成字节码。你知道 AppleScript Editor 是如何进行语法着色的吗?它首先对其进行编译,然后对生成的字节码进行反编译,然后语法着色是微不足道的。无论如何,当您驱动其他应用程序时,大部分时间都花在了繁重的进程间通信机制上。我认为编程语言的选择在这里并不重要。
    • 另外,不要因为 ObjC 是一种编译语言而感到兴奋……这表明你是多么年轻。在 Objective-C 中,方法是在运行时分派的,与 C++ 相比,它主要是在编译时确定的。所以 Objective-C 被认为是一种缓慢的、类似脚本的语言!
    • 每个人都应该信任@Philip ...我并没有完全使用 AppleScript。你觉得 ObjC-AppScript appscript.sourceforge.net/objc-appscript/index.html 怎么样?
    【解决方案2】:

    最简单的方法是使用NSAppleScript

    NSAppleScript *script = [[NSAppleScript alloc] 
        initWithSource:@"tell application \"Adium\" to go away with message \"Zoned in for Maths.\""
    ];
    

    如需更强大的脚本访问方式,请使用Scripting Bridge。 Scripting Bridge 至少需要 10.5 SDK。您首先需要准备您的应用程序。

    1. 使用sdef 和sdp 命令行实用程序为您希望控制的应用程序生成头文件(有关详细信息,请参阅“Preparing to Code”)。
    2. 将生成的标头添加到您的项目中。
    3. 将 ScriptingBridge 框架添加到您的项目中。之后,您可以使用 Objective-C 调用来控制其他应用程序。

    之后,您可以使用 Objective-C 向应用程序发送脚本命令。

    AdiumApplication *adium = [SBApplication applicationWithBundleIdentifier:@"com.adiumX.adiumX"];
    for (AdiumAccount* acct in [adium accounts]) {
        [acct goAwayWithMessage:(AdiumRichText *)@"Zoned in for Maths."];
    }
    

    状态消息是 Adium 的富文本类型(实际上是 NSTextStorage),但它可以从纯文本转换,因此传递 NSString 而不是真正的 AdiumRichText 应该可以正常工作。

    有几个箍要跳过。例如,您不能在目标应用程序中直接使用其ObjC 类create scripting objects;您必须使用classForScriptingClass: 来获取类,然后您可以使用它来正常创建对象(即alloc 和init、initWithProperties 等)。

    // creating an AdiumContactGroup
    NSDictionary *props = [NSDictionary 
        dictionaryWithObjectsAndKeys:
            @"mathies",@"name",
            nil
    ];
    AdiumContactGroup *mathies= [[[[adium classForScriptingClass:@"contact group"] alloc] 
                                  initWithProperties:props]
                                 autorelease];
    if (mathies) {
        [[adium contactGroups] addObject:mathies];
    }
    

    请注意,其他语言(如 Python 和 Ruby)也有脚本绑定。

    【讨论】:

    • +1 用于注意 Scripting Bridge 的功能。 Scripting Bridge 的显示停止问题出现在[[adium contactGroups] addObject:mathies];:如果应用程序没有放置新创建对象的公共容器 (SBElementArray),您可以'不要使用它。所有真正有用的功能都带有一个公共容器。许多应用程序不是以这种方式构建的(我经常在此处想到 Adob​​e Photoshop,我经常编写脚本),并且完全违背 Applescript 以本机形式运行的方式。
    【解决方案3】:

    其他人提到发送完整的 Applescript 或使用 Scripting Bridge。第三种选择是使用Appscript,它也可用于 Python 和 Ruby。在某些方面,它比使用 Scripting Bridge 更简洁 (IMO)。而且肯定更容易。尽管在其他方面 Scripting Bridge 更好。它还具有名为 ASTranslate 的应用程序的优势,它将大多数 Applescript 调用转换为 Appscript。这是您的小 Applescript 示例的 Appscript。

    ADApplication *adium = [ADApplication applicationWithName: @"Adium"];
    ADGoAwayCommand *cmd = [[adium goAway] withMessage: @"Zoned in for Maths."];
    id result = [cmd send];
    

    【讨论】:

    • 只是一个注释,因为我在其他 cmets 中看到了一些东西。 Appscript 附带了一个 XCode 项目。只需选择您的操作系统,构建,然后将 Appscript.framework 复制到 ~/Library/Frameworks。
    猜你喜欢
    • 1970-01-01
    • 2010-09-18
    • 2010-12-17
    • 2017-11-21
    • 2013-06-26
    • 1970-01-01
    • 2022-07-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多