How to call a Swift function (defined in XCode) from AppleScript

I’m new here so forgive me if this has been already discussed. I couldn’t find it (so far).

I’m working on a proof of principle and right now that calls for being able to create a new window with a different title on each Mission Control Desktop. I have not been able to tell either AppleScript or Swift to move a new window to another desktop nor to create a new window anywhere other than the current desktop. Fine, I’ll change desktops and then create the window. That means being able to run the app/script/whatever from a Desktop where it isn’t already running. My idea for that is a Keyboard Maestro hotkey that will run an AppleScript that will call the createNewWindowWithTitle function in my DeskSpaceID app.

When I run My XCode app, it currently makes an app window and then makes another window using the createNewWindowWithTitle function, just a minimal window given a title. If I run the function createNewWindowWithTitle from inside the AppDelegate.swift file, it works Just Fine. I’ve added Scriptable to the Info.plist file to enable AppleScript. When I use an AppleScript call like:

tell application "DeskSpaceID"
	createNewWindowWithTitle("My New Window", 400, 200)
end tell

to call the function in my app, DeskSpaceID I get an error:

DeskSpaceID got an error: Can’t continue createNewWindowWithTitle.

I’m not sure what “Can’t continue” is trying to tell me. I think it means that it got into but couldn’t run the function.

Here’s my complete AppDelegate.swift file:

//  AppDelegate.swift
//  DeskSpaceID
//  Created by August Mohr on 3/13/23.
//  Copyright © 2023 August Mohr. All rights reserved.

import Cocoa
import AppKit

class AppDelegate: NSObject, NSApplicationDelegate {

    @IBOutlet weak var window: NSWindow!

    func applicationWillFinishLaunching(_ notification: Notification) {
        UserDefaults.standard.set(false, forKey: "NSFullScreenMenuItemEverywhere")

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Insert code here to initialize your application
        createNewWindowWithTitle("New Window from DidFinishLaunching", width: 450, height: 100)

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    @objc func createNewWindowWithTitle(_ title: String, width: CGFloat, height: CGFloat) {
        let screenMaxY = NSScreen.main?.visibleFrame.maxY ?? 800
        let y = screenMaxY - height
        let window = NSWindow(contentRect: NSRect(x: 0, y: y,
                width: width, height: height),
                styleMask: [NSWindow.StyleMask.titled],
                backing: NSWindow.BackingStoreType.buffered,
                defer: false)
        window.title = title


Do I need to create a onCreateNewWindowWithTitle handler in either Swift or ApplScript? Some posts in various places that seem vaguely related to doing this seem to suggest that, but I’m new enough to this whole subject that I’m having trouble sorting out the layers.

Can someone point me to where this topic is explained or give me a hint about what’s not working right in what I’m doing?

BTW, I’m running on Mojave (about to upgrade to Catalina) using XCode 11.3.1. I have the XCode project set to use Swift 5 and XIB with a target of macOS 10.14 (Mojave).

If I need to upgrade to Catalina to do what I want, that’s OK. There are some folks who have a peripheral interest in my project who are also so still stuck on Mojave, so if I can make something that will work for them, great, but it’s not a requirement.


Welcome to the forum! I think you might be operating under an assumption that making your app “scriptable” will automatically open up access from AppleScript to the Swift-based functions/methods in your app. This is not the case.

Usually to make an app scriptable it requires a combination of turning on that switch you mentioned, adding specifications for commands, types, etc., to a “scripting dictionary” (.sdef) file for your app, and implementing custom methods in your app to handle scripting inquiries. You can read more about the whole process of making an app scriptable in many places, but here is one good introduction: Making Your Mac App’s Data Scriptable ·

1 Like

Thanks @redsweater , from a first glance, that seems to be what I was asking for.

You are correct, I did think that simply turning on that switch might be enough to expose my apps internal functions to AppleScript. I had not found anything referring to a “scripting dictionary” (.sdef) file.

I did find references to handlers, but they were mostly in AppleScript files, which is not what I need. Mostly all I’ve found has been how to run AppleScript from my app, which is not what I need either.

I’ve been skipping articles with titles like the one you suggested because I’ve not been concerned about transferring data, especially from my app because it won’t have any data except the list of window titles and maybe which windows are in the current Desktop Workspace. I just want to run the function I’ve defined. I guess I’m not going to find articles related only to my special case.

Thanks again for the pointer to this article.

I found another tutorial that covers the same ground but with a more complex app than the “Save Data in an Array and Retrieve It” example above. This one presents an example of a To-Do-List app: Making A Mac App Scriptable Tutorial.

Unfortunately, it’s written in Swift 3 so my XCode 11.3 gave me the message:

Unsupported Swift Version

The target “Scriptable Tasks” contains source code developed with Swift 3.x. This version of Xcode does not support building or migrating Swift 3.x targets.

Use Xcode 10.1 to migrate the code to Swift 4.

I note that the latest XCode 10 version was 10.3, so I wondered about that 10.1 version recommendation. No, XCode 10.3 does not support migrating Swift 3 code to Swift 4 and gives the error message when opening the project. XCode 10.1 is available at: More Downloads (Apple sign in required) and will run the project just fine.

I hope this helps someone looking for the same info that I am.