AppIntent

AppIntentManager is used to register and manage AppIntents in the Scripting app. It serves as the core mechanism for executing script logic behind controls in Widgets, Live Activities, and ControlWidgets.

All AppIntents must be defined in the app_intents.tsx file. When an intent is executed, the script runs in the "app_intents" environment (Script.env === "app_intents").

Once registered, these intents can be triggered by Button and Toggle controls within Widgets, Live Activities, or ControlWidgets, allowing users to define interactive behavior via script.


1. Type Definitions

AppIntent<T>

Represents a concrete intent instance with parameters and metadata.

Property Type Description
script string The internal script path. Automatically generated by the system.
name string The name of the AppIntent. Must be unique.
protocol AppIntentProtocol The protocol the intent conforms to (e.g., general, audio, Live Activity).
params T The parameters to be passed when the intent is executed.

AppIntentFactory<T>

A factory function that creates an AppIntent instance with specified parameters.

1type AppIntentFactory<T> = (params: T) => AppIntent<T>

AppIntentPerform<T>

A function that handles intent execution logic asynchronously.

1type AppIntentPerform<T> = (params: T) => Promise<void>

AppIntentProtocol

An enumeration that defines the behavior type of the intent.

Enum Value Description
AppIntent (0) A general-purpose AppIntent for typical operations.
AudioPlaybackIntent (1) An intent that plays, pauses, or otherwise modifies audio playback.
AudioRecordingIntent (2) (iOS 18.0+) An intent that starts, stops, or modifies audio recording. Note: On iOS/iPadOS, when using the AudioRecordingIntent protocol, you must start a Live Activity at the beginning of the recording and keep it active for the entire session. If you don't, the recording will be automatically stopped.
LiveActivityIntent (3) An intent that starts, pauses, or modifies a Live Activity.

2. AppIntentManager Class

AppIntentManager.register<T>(options): AppIntentFactory<T>

Registers a new AppIntent by specifying its name, protocol, and perform logic. When a control (e.g., Button or Toggle) triggers the intent, the associated perform function is called.

1static register<T = undefined>(options: {
2  name: string;
3  protocol: AppIntentProtocol;
4  perform: AppIntentPerform<T>;
5}): AppIntentFactory<T>

Parameters:

Property Type Description
name string A unique identifier for the AppIntent.
protocol AppIntentProtocol The protocol this intent implements.
perform AppIntentPerform<T> The asynchronous function executed when the intent is triggered. The params argument is passed from the control.

Returns:

  • AppIntentFactory<T>: A factory function that creates an AppIntent instance with the specified parameters.

Example:

1// app_intents.tsx
2export const ToggleDoorIntent = AppIntentManager.register({
3  name: "ToggleDoorIntent",
4  protocol: AppIntentProtocol.AppIntent,
5  perform: async ({ id, newState }: { id: string; newState: boolean }) => {
6    // Custom logic: toggle the door state
7    await setDoorState(id, newState)
8    // Notify UI to refresh toggle state
9    ControlWidget.reloadToggles()
10  }
11})

In a control view file (e.g., control_widget_toggle.tsx):

1ControlWidget.present(
2  <ControlWidgetToggle
3    intent={ToggleDoorIntent({ id: "door1", newState: !currentState })}
4    label={{
5      title: "Door 1",
6      systemImage: currentState ? "door.garage.opened" : "door.garage.closed"
7    }}
8    activeValueLabel={{ title: "The door is opened" }}
9    inactiveValueLabel={{ title: "The door is closed" }}
10  />
11)

In a widget file (widget.tsx):

1<Toggle
2  title="Door 1"
3  value={currentState}
4  intent={ToggleDoorIntent({ id: "door1", newState: !currentState })}
5/>

3. Execution Environment

All AppIntents registered via AppIntentManager are executed in the "app_intents" environment. This allows safe use of APIs suitable for background execution, such as:

  • Fetching data from the network
  • Controlling Live Activities
  • Triggering control view refreshes

4. Best Practices

  1. Centralized Definitions: All AppIntents must be defined in app_intents.tsx for discoverability and maintainability.

  2. Strong Typing: Define explicit parameter types T for both perform and control usage to benefit from type checking and autocomplete.

  3. Choose the Right Protocol:

    • General operation → AppIntent
    • Audio playback → AudioPlaybackIntent
    • Audio recording → AudioRecordingIntent (requires iOS 18+, with Live Activity)
    • Live Activity control → LiveActivityIntent
  4. Trigger UI Updates: If the intent modifies a UI state (e.g., toggle), call:

    • ControlWidget.reloadButtons()
    • ControlWidget.reloadToggles()
    • Widget.reloadAll() depending on where the control is hosted.