我正在尝试编写一个简单的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的例子,当我运行它时,自定义属性与核心属性一起出现。
我觉得我已经尝试了一百种变化,并阅读了一百个例子,但无法获得任何工作。任何帮助表示赞赏。
答案 0 :(得分:2)
您的SDEF文件存在许多问题。
虽然这不是一个主要问题,但在定义自己的“类型”(OSType
代码)时,所有小写字母在历史上都是为Apple保留的。因此,您应该执行类似'Smas'
或'sMas'
但不是'smas'
的操作。
在网络浏览器中,这可能是一个拼写错误,但您在inhereits
行中拼错了<class name="application" code="smaa" inhereits="application"...
。拼写正确非常重要,这样您就可以使用自己的附加属性正确“扩展”基础AppleScript application
类。这可能是您只在AppleScript编辑器中看到默认应用程序属性的原因。 (虽然单独纠正拼写可能会让事情发生变化,但您还应该做出其他更正。)
您正在尝试指定“扩展”application
AppleScript类的Cocoa类为AppDelegate
,但这是有问题的,因为AppDelegate
不会继承自NSApplication
{1}}类似于Apple的示例.sdef中指定的,而是继承自普通的NSObject
。
在继续讨论如何重新编写SDEF之前,我将回顾一下Apple的示例SDEF如何将自定义属性添加到默认的AppleScript application
类背后的基本思想。 AppleScript application
类对应于NSApplication
Cocoa类。当您启动应用程序时,OS X会创建一个NSApplication
实例(或其子类,由应用程序的Info.plist文件中的NSPrincipalClass
条目指定)。此实例管理应用程序。在Cocoa中,有两种方法可以将其他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
。我添加了一个名为foobaz
且类型为text
的自定义AppleScript属性。 (AppleScript text
类将对应于Cocoa NSString
类。同样重要的是我已经指定访问此自定义属性的Cocoa键是foobaz
。此“Cocoa键”指定将用于提供属性值的Objective-C方法的名称。上面定义的配置指定可以通过调用foobaz
对象的共享实例上的foobaz
方法来获取自定义NSApplication
属性。
为了在Cocoa方面实现这一点,我在(MDScriptingAdditions)
上定义了NSApplication
类别,如下所示:
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:
文本字段中显示的值更改为您设置的值,如下图所示:
答案 1 :(得分:0)
我唯一看到的就是你的sdef中的一个问题。此行的代码需要为“capp”。这是标准的,在任何sdef文件中都是一样的。它由Apple定义,因此您需要它。
<class name="application" code="smaa" inhereits="application"
description="Application object.">
执行此操作后,您可以像这样访问该方法......
tell application "StautsMenuApp" to foobaz