AppleScript很酷。我可以在普通的Objective-C中做同样的事情吗?

时间:2010-12-11 10:43:58

标签: objective-c applescript

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

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

(如果你想知道这应该是什么。为了实际开始学习,我需要创建一个会改变我的IM状态的应用程序,当然......)

我在脚本编辑器中尝试过它,它有效,而且我很确定从Cocoa应用程序调用AppleScript将是微不足道的。

但是

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

有没有办法在没有AppleScript的情况下执行与上述代码相同的操作,无论如何以简单的Objective-C?

有人会指出我的相关文件吗?我试过谷歌,但就像我甚至不知道我在寻找什么。

谢谢!

3 个答案:

答案 0 :(得分:10)

Mac OS X中的进程间通信由Apple Events完成。 AppleScript是向其他应用程序发送和接收Apple Events的一种方法。

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

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

如果你想做更复杂的事情,Scripting Bridge是要走的路。此机制将Apple Events的对象层次结构映射到Objective-C的对象层次结构。

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

好吧,我们中的一些老计时器认为使用Objective-C是一种娘娘腔的方式。如果你这么认为,你应该直接处理名为AEDesc的C结构等。请参阅Apple Events programming guidethe corresponding reference

但是,我认为使用OS X的人都是新手。真正的人使用Linux。

我父亲会说使用GUI的人太被宠坏了。

关键是,你不必关心它是否是新手的方式。重要的是你能否实现自己想要的目标。实际上,AppleScript是一种非常强大的动态语言,其功能并未得到很多人的认可。阅读AppleScript language guide并感到惊讶。

答案 1 :(得分:6)

最简单的方法是使用NSAppleScript

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

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

  1. 使用sdefsdp命令行实用程序为您要控制的应用程序生成头文件(有关详细信息,请参阅“Preparing to Code”)。
  2. 将生成的标题添加到项目中。
  3. 将ScriptingBridge框架添加到您的项目中。之后,您可以使用Objective-C调用来控制其他应用程序。
  4. 之后,您可以使用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:来获取该类,然后您可以使用该类来正常创建对象(即allocinitinitWithProperties& c。)。

    // 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)也有Scripting绑定。

答案 2 :(得分:1)

其他人提到发送完整的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];