2021 App Services
WWDC21 · 27 min · App Services
Meet Shortcuts for macOS
Shortcuts is coming to macOS, and your apps are a key part of that process. Discover how you can elevate the capabilities of your app by exposing those features as Shortcuts actions. We’ll show you how to build actions for your macOS apps built with Catalyst or AppKit, deploy actions across platforms, publish and share shortcuts, and enable your app to run shortcuts from other apps. We’ll also take you through how Shortcuts fits in with existing Mac automation technologies like Automator and AppleScript.
Watch at developer.apple.com ↗Code shown on screen · 6 snippets
Adding Intent dispatch method in SwiftUI
import SwiftUI
import Intents
@main
struct SouperTaskApp: App {
(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
class AppDelegate: NSObject, NSApplicationDelegate {
func application(_ application: NSApplication, handlerFor intent: INIntent) -> Any? {
}
} Resolve intent
class IntentHandler: NSObject, CreateTaskIntentHandling {
func resolveTitle(for intent: CreateTaskIntent, with completion: @escaping (INStringResolutionResult) -> Void) {
guard let title = intent.title, !title.isEmpty else {
return completion(.needsValue())
}
return completion(.success(with: title))
}
func resolveDueDate(for intent: CreateTaskIntent, with completion: @escaping (CreateTaskDueDateResolutionResult) -> Void) {
guard let dateComponents = intent.dueDate else {
return completion(.needsValue())
}
return completion(.success(with: dateComponents))
}
...
} Date range validation in dueDate resolve method
func resolveDueDate(for intent: CreateTaskIntent, with completion: @escaping (CreateTaskDueDateResolutionResult) -> Void) {
guard
let dateComponents = intent.dueDate,
let dueDate = Calendar.current.date(from: dateComponents)
else {
return completion(.needsValue())
}
if dueDate < Date() {
return completion(.unsupported(forReason: .invalidDate))
}
return completion(.success(with: dateComponents))
} Handle intent
class IntentHandler: NSObject, CreateTaskIntentHandling {
func handle(intent: CreateTaskIntent, completion: @escaping (CreateTaskIntentResponse) -> Void) {
let title = intent.title!
let dueDate = intent.dueDate!
let task = createTask(name: title, due: dueDate)
let response = CreateTaskIntentResponse(code: .success, userActivity: nil)
response.task = task
completion(response)
}
} Running Shortcut from AppleScript
tell application "Shortcuts Events"
run the shortcut whose name is "Make GIF"
end tell Using scripting bridge
import ScriptingBridge
@objc protocol ShortcutsEvents {
@objc optional var shortcuts: SBElementArray { get }
}
@objc protocol Shortcut {
@objc optional var name: String { get }
@objc optional func run(withInput: Any?) -> Any?
}
extension SBApplication: ShortcutsEvents {}
extension SBObject: Shortcut {}
guard
let app: ShortcutsEvents = SBApplication(bundleIdentifier: "com.apple.shortcuts.events"),
let shortcuts = app.shortcuts else {
print("Couldn't access shortcuts")
return
}
guard let shortcut = shortcuts.object(withName: "Make GIF") as? Shortcut else {
print("Shortcut doesn't exist")
return
}
_ = shortcut.run?(withInput: nil) Resources
Related sessions
-
40 min -
27 min -
23 min -
22 min