【问题标题】:Cannot get Apple's SimpleScripting example to work when using NSApplicationDelegate使用 NSApplicationDelegate 时无法让 Apple 的 SimpleScripting 示例工作
【发布时间】:2013-02-17 21:12:55
【问题描述】:

我正在尝试编写一个简单的 Objective-C 应用程序:我只想要一个可以在状态栏中显示一个单词并允许通过 AppleScript 更新该单词的应用程序。老实说,我对 AppleScript 知之甚少,对 Objective-C 也一无所知。但是,这并不难,因为我只花了 2 个小时就获得了一个菜单栏应用程序,该应用程序具有菜单项并响应诸如“退出”之类的核心 AppleScript 命令,所以我已经完成了 95% 的工作。不幸的是,我花了接下来的 6 个小时试图找到一种方法来为这个应用程序提供一个我可以通过 AppleScript 获取和设置的简单属性。

这是我的 .h 代码:

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate> {
    NSWindow *window;
    IBOutlet NSMenu *statusMenu;
    NSStatusItem *statusItem;
}
@property (assign) IBOutlet NSWindow *window;
- (NSString*) foobaz;
@end

foobaz 方法是我用来尝试创建可读属性的方法(*window 是 XCode 提供的样板文件的一部分,与手头的问题无关)。这是我的 .sdef 文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary xmlns:xi="http://www.w3.org/2003/XInclude">
  <xi:include
    href="file:///System/Library/ScriptingDefinitions/CocoaStandard.sdef"
    xpointer="xpointer(/dictionary/suite)"/>
  <suite name="StatusMenuApp suite" code="smas"
    description="StatusMenuApp specific classes.">
    <class name="application" code="smaa" inhereits="application"
      description="Application object.">
      <cocoa class="AppDelegate"/>
      <property name="foobaz" code="smas" type="text" access="r"/>
    </class>
  </suite>
</dictionary>

所以我已经像 Apple 的 SimpleScripting 示例一样设置了它:https://developer.apple.com/library/mac/#samplecode/SimpleScripting/Introduction/Intro.html

但是,我尝试在脚本编辑器中运行它:

tell application "StautsMenuApp"
    properties
end tell

我只得到了核心属性的列表,没有提及foobaz,这与 Apple 的示例不同,其中自定义属性在我运行时出现在核心属性旁边。

我觉得我已经尝试了一百种变体并阅读了一百个示例,但没有任何效果。任何帮助表示赞赏。

【问题讨论】:

    标签: cocoa properties applescript sdef nsapplication-delegate


    【解决方案1】:

    您的 SDEF 文件存在许多问题。

    1. 虽然这不是主要问题,但在定义您自己的“类型”(OSType 代码)时,所有小写字母历来都是为 Apple 保留的。所以,你应该做类似'Smas''sMas' 但不是'smas'

    2. 这可能是网络浏览器中的拼写错误,但您在&lt;class name="application" code="smaa" inhereits="application"... 行中拼错了inhereits。拼写正确很重要,这样您就可以使用自己的附加属性正确“扩展”基本 AppleScript application 类。这可能是您在 AppleScript 编辑器中只看到默认应用程序属性的原因。 (虽然单独更正拼写可能会让事情正常进行,但您还应该进行其他更正)。

    3. 1234563例如.sdef,它继承自普通的NSObject

    在继续我将如何重写 SDEF 之前,我将回顾一下 Apple 示例 SDEF 如何将自定义属性添加到默认 AppleScript application 类的基本思想。 AppleScript application 类对应于 NSApplication Cocoa 类。当您启动应用程序时,OS X 会创建一个 NSApplication 实例(或其子类,由应用程序的 Info.plist 文件中的 NSPrincipalClass 条目指定)。此实例管理应用程序。在 Cocoa 中,有 2 种可能的方法可以将附加的 AppleScript 属性添加到现有的 NSApplication 类中:1) 创建包含附加属性的 NSApplication 的自定义子类或 2) 使用 Objective-C 类别来扩展现有的NSApplication 按原样上课。 (在 Cocoa 中,Objective-C 类别是一种向现有类添加附加功能的方法,而不会带来子类化引入的潜在复杂性)。 Apple 的 SimpleScripting 示例使用后一种方法(Objective-C 类别)来添加附加功能。

    以下是我将如何重写 SDEF。

    SimpleScriptingAppDelegate.sdef:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
    <dictionary xmlns:xi="http://www.w3.org/2003/XInclude">
        <xi:include
        href="file:///System/Library/ScriptingDefinitions/CocoaStandard.sdef"
        xpointer="xpointer(/dictionary/suite)"/>
        <suite name="StatusMenuApp suite" code="SSAD"
                     description="StatusMenuApp-specific classes.">
            <class name="application" code="capp" inherits="application"
                                     description="Application object.">
                <cocoa class="NSApplication"/>
                <property name="foobaz" code="Foob"
                    description="Description of the foobaz property." type="text">
                    <cocoa key="foobaz"/>
                </property>
            </class>
        </suite>
    </dictionary>
    

    您会注意到我已指定我正在创建一个自定义 AppleScript application 类,该类继承自标准 AppleScript application 类。我已经指定这个自定义application 的 Cocoa 类是NSApplication。我添加了一个自定义 AppleScript 属性,其名称为 foobaz,其类型为 text。 (AppleScript text 类将对应于 Cocoa NSString 类)。同样重要的是,我已指定访问此自定义属性的 Cocoa 键是 foobaz。这个“Cocoa 键”指定了用于为属性提供值的 Objective-C 方法的名称。上面定义的配置指定可以通过在NSApplication对象的共享实例上调用foobaz方法来获取自定义的foobaz属性。

    为了在 Cocoa 方面实现这一点,我在 NSApplication 上定义了 (MDScriptingAdditions) 类别,如下所示:

    MDNSApplicationScriptingAdditions.h:

    @interface NSApplication (MDScriptingAdditions)
    
    - (NSString *)foobaz;
    - (void)setFoobaz:(NSString *)aFoobaz;
    
    @end
    

    MDNSApplicationScriptingAdditions.m:

    #import "MDNSApplicationScriptingAdditions.h"
    #import "AppDelegate.h"
    
    @implementation NSApplication (MDScriptingAdditions)
    
    - (NSString *)foobaz {
        return [(AppDelegate *)[NSApp delegate] foobaz];
    }
    
    - (void)setFoobaz:(NSString *)aFoobaz {
        return [(AppDelegate *)[NSApp delegate] setFoobaz:aFoobaz];
    }
    @end
    

    您可以看到,我基本上将这些方法的处理转发给 AppDelegate 类,这就是您想要的设置方式。

    AppDelegate.h:

    @interface AppDelegate : NSObject <NSApplicationDelegate> {
        IBOutlet NSWindow                    *window;
        IBOutlet NSTextField                *foobazTextField;
    
        NSString                            *foobaz;
    }
    - (NSString *)foobaz;
    - (void)setFoobaz:(NSString *)aFoobaz;
    @end
    

    此设置允许您通过 AppleScript 获取和设置自定义 foobaz 属性。设置该值将导致 foobaz: 文本字段中显示的值更改为您设置的值,如下图所示:

    示例项目:SimpleScriptingAppDelegate.zip

    【讨论】:

      【解决方案2】:

      我看到的唯一一件事就是你的 sdef 有问题。此行的代码必须是“capp”。这是标准的,这在任何 sdef 文件中都是相同的。它是由 Apple 定义的,所以你需要它。

      <class name="application" code="smaa" inhereits="application"
            description="Application object.">
      

      在你这样做之后,你会像这样访问那个方法......

      tell application "StautsMenuApp" to foobaz
      

      【讨论】:

        猜你喜欢
        • 2013-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-07
        • 1970-01-01
        • 2018-09-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多