Friday, December 15, 2017

#1 2016-03-18 02:17:55 pm

Registered: 2015-04-03
Posts: 66

Make Cocoa app scriptable

I'd like to add one simple script command to a Cocoa/Swift app. However all the example tutorials are 1) really old 2) far more complicated than what I have in mind.

This is what I have in mind:


--I'd like my app to respond to this command:
tell application "MyApp"
end tell

That's it. I know I need to build a sdef file and enable scriptability in xcode, but since I skipped learning ObjC and went straight to Swift, the rest of the process is very confusing.

Any pointers would be greatly appreciated.

Last edited by tneison (2016-03-18 02:18:51 pm)



#2 2016-03-20 08:58:32 pm

Registered: 2015-04-03
Posts: 66

Re: Make Cocoa app scriptable

Okay I've got it. I was able to dig up an Apple document ( … e_txt.html) and find an example in Swift ( … ementation). My example isn't that useful since desktop notifications are easily implemented using ASOC, but it's a clear way to illustrate an Applescript command with arguments.

The sdef file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">

<!-- declare the namespace for using XInclude so we can include the standard suite -->
<dictionary xmlns:xi="">
    <!-- use XInclude to include the standard suite -->
    <xi:include href="file:///System/Library/ScriptingDefinitions/CocoaStandard.sdef" xpointer="xpointer(/dictionary/suite)"/>
    <!-- specific suite(s) for the application follow... -->
    <suite name="Simple Desktop Notification" code="Nofy" description="A test creating a simple Applescript command with 2 arguments.">
        <command name="notiphy" code="NofyParm" description="Choose text values of the notiphication">
            <cocoa class="NotiphyCMD.NotiphyWithParams"/>
            <parameter name="with title" code="NTle" type="text" optional="no"
                description="a title parameter.">
                <cocoa key="NotiphyTitle"/>
            <parameter name="and subtitle" code="NTSl" type="text" optional="yes"
                description="a subtitle parameter.">
                <cocoa key="NotiphySubtitle"/>
            <result type="boolean" description="The result of the invocation. True if it succeeds, False if it does not"/>

The Swift class instantiated by the Applescript command:

import Cocoa

class NotiphyWithParams: NSScriptCommand, NSUserNotificationCenterDelegate {
    var notiphy = NSUserNotification()
    var notiphyCtr = NSUserNotificationCenter.defaultUserNotificationCenter()

    override func performDefaultImplementation() -> AnyObject? {
        let parms = self.evaluatedArguments
        var aTitle = ""
        var aSubTitle = ""
        if let args = parms {
            if let title = args["NotiphyTitle"] as? String {
                aTitle = title
            if let subtitle = args["NotiphySubtitle"] as? String {
                aSubTitle = subtitle
        notiphy.title = aTitle
        notiphy.subtitle = aSubTitle
        if aTitle == "" && aSubTitle == "" {
            return false
        return true
    func userNotificationCenter(center: NSUserNotificationCenter, shouldPresentNotification notification: NSUserNotification) -> Bool {
        return true

Finally, the Applescript command:


tell application "NotiphyCMD"
   notiphy with title "Hello" and subtitle "world!"
end tell

A few notes:

in the sdef file,


is peculiar in that in ObjC


is all that's needed to refer to the class, but in Swift the dot notation is needed to resolve the path from the application to the class.


is a subclass of


. This is what does all the work. To get our subclass to respond to a scripting command, we use

override func performDefaultImplementation()

This allows us to add 'notiphy' as our custom command. Expected arguments are added in the sdef file using <parameter. They are accessible inside the override func as a dictionary called




Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)