Jolly Roger Jolly Roger - 1 year ago 158
AppleScript Question

Accessing property in Cocoa AppDelegate (NSApplicationDelegate) from AppleScript

I have a very basic Cocoa application written in Xcode, and I'm trying to access a property of my application delegate with a simple AppleScript script:

tell application "HelloWorld"
set appDelegateProperty to property1
end tell

The information in the Cocoa Scripting Guide seems pretty straight forward. While it seems like the code I've written is key-value coding (KVC) compliant, I am seeing errors that indicate otherwise.

I've added a synthesized property of type
to my
class, setting it to
in the
method. And I added entries to my scripting definition (SDEF) file to allow access to the property from AppleScript.

Here's the relevant code (you can download a zipped copy, or browse the source, of the Xcode project on this web page):


I added these keys to enable AppleScript support in the application:



#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate>
@property NSString* property1;


#import "AppDelegate.h"

@interface AppDelegate ()
@property (weak) IBOutlet NSWindow *window;

@implementation AppDelegate
@synthesize property1;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
property1 = @"test";


<?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"/>

When I start the application in the Xcode debugger and execute this AppleScript code in Script Editor, here is the error I see in the Script Editor console:

Script Editor Console Output

error "HelloWorld got an error: AppleEvent handler failed." number -10000

Xcode Debugger Console Output

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)"

Troubleshooting Notes

Somehow, my code is not in fact KVC compliant, though I am unsure how or why.

I suspect there may be an issue with the fact that the property is in the application delegate rather than the
class itself, but I could be wrong.

I've set the bindings debug log level as shown in the "Troubleshooting Cocoa Bindings" section of the Cocoa Bindings Programming Topics documentation to troubleshoot the bindings:

defaults write net.none.HelloWorld NSBindingDebugLogLevel 1

I've also set the scripting debug log level to 1 as shown in the "Turn On Debugging Output for Scripting" section of the Cocoa Scripting Guide to see more detailed debug output like so:

defaults write net.none.HelloWorld NSScriptingDebugLogLevel 1

Finally, I've followed instructions in the "Examining Scriptability Information in Your Application" section of the Cocoa Scripting Guide to output the descriptions of scripting information Cocoa pulls from the SDEF. Here's that debugger console command and its output:

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')

Any ideas?

Answer Source

If the key is in AppDelegate you have to implement

- (BOOL)application:(NSApplication *)sender delegateHandlesKey:(NSString *)key
    return [key isEqualToString:@"property1"]; 

For multiple keys declare a NSSet property keySet containing all keys and return

return [keySet containsObject:key]; 

You don't need to specify the cocoa key property1 in the sdef file since the name match the selector.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download