从 AppleScript 访问 Cocoa AppDelegate (NSApplicationDelegate) 中的 属性
Accessing property in Cocoa AppDelegate (NSApplicationDelegate) from AppleScript
我有一个用 Xcode 编写的非常基本的 Cocoa 应用程序,我正在尝试使用简单的 AppleScript 脚本访问我的应用程序委托的 属性:
tell application "HelloWorld"
set appDelegateProperty to property1
end tell
Cocoa Scripting Guide 中的信息似乎非常简单明了。虽然看起来我编写的代码符合键值编码 (KVC) 标准,但我看到的错误表明情况并非如此。
我在 AppDelegate
class 中添加了一个名为 NSString
类型 NSString
的合成 属性,并将其设置为 @"test"
在 applicationDidFinishLaunching()
方法中。我在脚本定义 (SDEF) 文件中添加了条目,以允许从 AppleScript 访问 属性。
这里是相关代码(您可以在 this web page 上下载 Xcode 项目的压缩副本或浏览源代码):
Info.plist
我添加了这些键以在应用程序中启用 AppleScript 支持:
<key>NSAppleScriptEnabled</key>
<string>YES</string>
<key>OSAScriptingDefinition</key>
<string>HelloWorld.sdef</string>
AppDelegate.h
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property NSString* property1;
@end
AppDelegate.m
#import "AppDelegate.h"
@interface AppDelegate ()
@property (weak) IBOutlet NSWindow *window;
@end
@implementation AppDelegate
@synthesize property1;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
property1 = @"test";
}
@end
HelloWorld.sdef
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary title="HelloWorld">
<suite name="HelloWorld" code="HELO" description="HelloWorld scripting suite">
<class name="application" id="HELO" code="capp" description="top-level scripting object">
<cocoa class="NSApplication"/>
<property name="property1" code="Hadp" description="property1" type="text" access="r">
<cocoa key="property1"/>
</property>
</class>
</suite>
</dictionary>
当我在 Xcode 调试器中启动应用程序并在脚本编辑器中执行此 AppleScript 代码时,这是我在脚本编辑器控制台中看到的错误:
脚本编辑器控制台输出
error "HelloWorld got an error: AppleEvent handler failed." number -10000
Xcode 调试器控制台输出
2016-07-01 15:29:18.449 HelloWorld[90280:3166995] Command: Intrinsics.get
Direct Parameter: <NSPropertySpecifier: property1>
Receivers: <NSPropertySpecifier: property1>
Arguments: {
}
2016-07-01 15:29:18.449 HelloWorld[90280:3166995] An exception was thrown during execution of an NSScriptCommand...
2016-07-01 15:29:18.449 HelloWorld[90280:3166995] [<NSApplication 0x620000101560> valueForUndefinedKey:]: this class is not key value coding-compliant for the key property1.
2016-07-01 15:29:18.449 HelloWorld[90280:3166995] Result: (null)
2016-07-01 15:29:18.449 HelloWorld[90280:3166995] Error: -10000 "(null)"
故障排除说明
不知何故,我的代码实际上不符合 KVC,但我不确定如何或为什么。
我怀疑 属性 在 应用程序委托 而不是 NSApplication
class 中可能存在问题本身,但我可能是错的。
我设置了绑定调试日志级别,如 Cocoa 绑定编程主题文档的 "Troubleshooting Cocoa Bindings" 部分所示,以解决绑定问题:
defaults write net.none.HelloWorld NSBindingDebugLogLevel 1
我还将脚本调试日志级别设置为 1,如 Cocoa 脚本指南的 "Turn On Debugging Output for Scripting" 部分所示,以查看更详细的调试输出,如下所示:
defaults write net.none.HelloWorld NSScriptingDebugLogLevel 1
最后,我按照 Cocoa 脚本指南 "Examining Scriptability Information in Your Application" 部分中的说明输出了从 SDEF Cocoa 提取的脚本信息的描述。这是调试器控制台命令及其输出:
po [NSClassFromString(@"NSScriptSuiteRegistry") sharedScriptSuiteRegistry]
Suite: Intrinsics ('intr'), hidden: yes
Name: "Intrinsics", description: ""
Class: item ('cobj'), superclass: <none>, hidden: no
Implementation class: NSObject
Name: "item", plural name: "items", description: "A scriptable object."
Attribute: classCode ('pcls'), type: type ('type'), access: read-only, hidden: no
Name: "class", description: "The class of the object."
Attribute: scriptingProperties ('pALL'), type: record ('reco'), access: read-write, hidden: no
Name: "properties", description: "All of the object's properties."
Default subcontainer: <none>
Supported command: delete, method: -
Supported command: exists, method: -
Supported command: set, method: -
Supported command: get, method: -
Supported command: count, method: -
Supported command: move, method: -
Supported command: duplicate, method: -
Primitive type: <none>
Command: get ('core'/'getd'), hidden: no
Implementation class: NSGetCommand
Name: "get", description: "Returns the value of the specified object(s)."
Unnamed argument ('----'), type: specifier ('obj '), optional: no
(No user-readable name or description needed for unnamed arguments)
Result type: any ('****')
Description: <none>
Command: set ('core'/'setd'), hidden: no
Implementation class: NSSetCommand
Name: "set", description: "Sets the value of the specified object(s)."
Unnamed argument ('----'), type: specifier ('obj '), optional: no
(No user-readable name or description needed for unnamed arguments)
Argument: Value ('data'), type: any ('****'), optional: no, hidden: no
Name: "to", description: "The new value."
Result type: <none> ('null')
Description: <none>
Value type: any ('****')
Implementation class: NSAppleEventDescriptor
Value type: boolean ('bool')
Implementation class: NSNumber
Value type: date ('ldt ')
Implementation class: NSDate
Value type: file ('file')
Implementation class: NSURL
Value type: integer ('long')
Implementation class: NSNumber
Value type: location specifier ('insl')
Implementation class: NSPositionalSpecifier
Value type: missing value ('msng')
Implementation class: NSNull
Value type: number ('nmbr')
Implementation class: NSNumber
Value type: point ('QDpt')
Implementation class: NSData
Value type: real ('doub')
Implementation class: NSNumber
Value type: record ('reco')
Implementation class: NSDictionary
Value type: rectangle ('qdrt')
Implementation class: NSData
Value type: specifier ('obj ')
Implementation class: NSScriptObjectSpecifier
Value type: text ('ctxt')
Implementation class: NSString
Value type: type ('type')
Implementation class: NSNumber
Object type: item ('cobj')
Suite: HelloWorld ('HELO'), hidden: no
Name: "HelloWorld", description: "HelloWorld scripting suite"
Class: application ('capp'), superclass: item, hidden: no
Implementation class: NSApplication
Name: "application", plural name: "applications", description: "top-level scripting object"
Attribute: property1 ('Hadp'), type: text ('ctxt'), access: read-only, hidden: no
Name: "property1", description: "property1"
Default subcontainer: <none>
Primitive type: <none>
Object type: application ('capp')
有什么想法吗?
如果密钥在 AppDelegate
你必须实施
- (BOOL)application:(NSApplication *)sender delegateHandlesKey:(NSString *)key
{
return [key isEqualToString:@"property1"];
}
对于多个键声明一个 NSSet
属性 keySet
包含所有键和 return
return [keySet containsObject:key];
您不需要在 sdef 文件中指定 cocoa key
property1
,因为名称与选择器匹配。
我有一个用 Xcode 编写的非常基本的 Cocoa 应用程序,我正在尝试使用简单的 AppleScript 脚本访问我的应用程序委托的 属性:
tell application "HelloWorld"
set appDelegateProperty to property1
end tell
Cocoa Scripting Guide 中的信息似乎非常简单明了。虽然看起来我编写的代码符合键值编码 (KVC) 标准,但我看到的错误表明情况并非如此。
我在 AppDelegate
class 中添加了一个名为 NSString
类型 NSString
的合成 属性,并将其设置为 @"test"
在 applicationDidFinishLaunching()
方法中。我在脚本定义 (SDEF) 文件中添加了条目,以允许从 AppleScript 访问 属性。
这里是相关代码(您可以在 this web page 上下载 Xcode 项目的压缩副本或浏览源代码):
Info.plist
我添加了这些键以在应用程序中启用 AppleScript 支持:
<key>NSAppleScriptEnabled</key>
<string>YES</string>
<key>OSAScriptingDefinition</key>
<string>HelloWorld.sdef</string>
AppDelegate.h
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property NSString* property1;
@end
AppDelegate.m
#import "AppDelegate.h"
@interface AppDelegate ()
@property (weak) IBOutlet NSWindow *window;
@end
@implementation AppDelegate
@synthesize property1;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
property1 = @"test";
}
@end
HelloWorld.sdef
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary title="HelloWorld">
<suite name="HelloWorld" code="HELO" description="HelloWorld scripting suite">
<class name="application" id="HELO" code="capp" description="top-level scripting object">
<cocoa class="NSApplication"/>
<property name="property1" code="Hadp" description="property1" type="text" access="r">
<cocoa key="property1"/>
</property>
</class>
</suite>
</dictionary>
当我在 Xcode 调试器中启动应用程序并在脚本编辑器中执行此 AppleScript 代码时,这是我在脚本编辑器控制台中看到的错误:
脚本编辑器控制台输出
error "HelloWorld got an error: AppleEvent handler failed." number -10000
Xcode 调试器控制台输出
2016-07-01 15:29:18.449 HelloWorld[90280:3166995] Command: Intrinsics.get
Direct Parameter: <NSPropertySpecifier: property1>
Receivers: <NSPropertySpecifier: property1>
Arguments: {
}
2016-07-01 15:29:18.449 HelloWorld[90280:3166995] An exception was thrown during execution of an NSScriptCommand...
2016-07-01 15:29:18.449 HelloWorld[90280:3166995] [<NSApplication 0x620000101560> valueForUndefinedKey:]: this class is not key value coding-compliant for the key property1.
2016-07-01 15:29:18.449 HelloWorld[90280:3166995] Result: (null)
2016-07-01 15:29:18.449 HelloWorld[90280:3166995] Error: -10000 "(null)"
故障排除说明
不知何故,我的代码实际上不符合 KVC,但我不确定如何或为什么。
我怀疑 属性 在 应用程序委托 而不是 NSApplication
class 中可能存在问题本身,但我可能是错的。
我设置了绑定调试日志级别,如 Cocoa 绑定编程主题文档的 "Troubleshooting Cocoa Bindings" 部分所示,以解决绑定问题:
defaults write net.none.HelloWorld NSBindingDebugLogLevel 1
我还将脚本调试日志级别设置为 1,如 Cocoa 脚本指南的 "Turn On Debugging Output for Scripting" 部分所示,以查看更详细的调试输出,如下所示:
defaults write net.none.HelloWorld NSScriptingDebugLogLevel 1
最后,我按照 Cocoa 脚本指南 "Examining Scriptability Information in Your Application" 部分中的说明输出了从 SDEF Cocoa 提取的脚本信息的描述。这是调试器控制台命令及其输出:
po [NSClassFromString(@"NSScriptSuiteRegistry") sharedScriptSuiteRegistry]
Suite: Intrinsics ('intr'), hidden: yes
Name: "Intrinsics", description: ""
Class: item ('cobj'), superclass: <none>, hidden: no
Implementation class: NSObject
Name: "item", plural name: "items", description: "A scriptable object."
Attribute: classCode ('pcls'), type: type ('type'), access: read-only, hidden: no
Name: "class", description: "The class of the object."
Attribute: scriptingProperties ('pALL'), type: record ('reco'), access: read-write, hidden: no
Name: "properties", description: "All of the object's properties."
Default subcontainer: <none>
Supported command: delete, method: -
Supported command: exists, method: -
Supported command: set, method: -
Supported command: get, method: -
Supported command: count, method: -
Supported command: move, method: -
Supported command: duplicate, method: -
Primitive type: <none>
Command: get ('core'/'getd'), hidden: no
Implementation class: NSGetCommand
Name: "get", description: "Returns the value of the specified object(s)."
Unnamed argument ('----'), type: specifier ('obj '), optional: no
(No user-readable name or description needed for unnamed arguments)
Result type: any ('****')
Description: <none>
Command: set ('core'/'setd'), hidden: no
Implementation class: NSSetCommand
Name: "set", description: "Sets the value of the specified object(s)."
Unnamed argument ('----'), type: specifier ('obj '), optional: no
(No user-readable name or description needed for unnamed arguments)
Argument: Value ('data'), type: any ('****'), optional: no, hidden: no
Name: "to", description: "The new value."
Result type: <none> ('null')
Description: <none>
Value type: any ('****')
Implementation class: NSAppleEventDescriptor
Value type: boolean ('bool')
Implementation class: NSNumber
Value type: date ('ldt ')
Implementation class: NSDate
Value type: file ('file')
Implementation class: NSURL
Value type: integer ('long')
Implementation class: NSNumber
Value type: location specifier ('insl')
Implementation class: NSPositionalSpecifier
Value type: missing value ('msng')
Implementation class: NSNull
Value type: number ('nmbr')
Implementation class: NSNumber
Value type: point ('QDpt')
Implementation class: NSData
Value type: real ('doub')
Implementation class: NSNumber
Value type: record ('reco')
Implementation class: NSDictionary
Value type: rectangle ('qdrt')
Implementation class: NSData
Value type: specifier ('obj ')
Implementation class: NSScriptObjectSpecifier
Value type: text ('ctxt')
Implementation class: NSString
Value type: type ('type')
Implementation class: NSNumber
Object type: item ('cobj')
Suite: HelloWorld ('HELO'), hidden: no
Name: "HelloWorld", description: "HelloWorld scripting suite"
Class: application ('capp'), superclass: item, hidden: no
Implementation class: NSApplication
Name: "application", plural name: "applications", description: "top-level scripting object"
Attribute: property1 ('Hadp'), type: text ('ctxt'), access: read-only, hidden: no
Name: "property1", description: "property1"
Default subcontainer: <none>
Primitive type: <none>
Object type: application ('capp')
有什么想法吗?
如果密钥在 AppDelegate
你必须实施
- (BOOL)application:(NSApplication *)sender delegateHandlesKey:(NSString *)key
{
return [key isEqualToString:@"property1"];
}
对于多个键声明一个 NSSet
属性 keySet
包含所有键和 return
return [keySet containsObject:key];
您不需要在 sdef 文件中指定 cocoa key
property1
,因为名称与选择器匹配。