Search code examples
iosswiftswiftuiappintents

How can a parameterised App Intent display additional parameters “below the fold”?


I'm adding App Intents to my iOS16 app using the App Intents framework.

One of the intents I want to add opens a list view of all events in my app's database. The view in the app has a number of filters available, and I'm trying to replicate some of those filters in the intent.

I've got a couple of options already coded – one AppEnum showing a time scope (past/future/all events), and one selector of publications (each event can have zero or one publication).

Following the techniques demonstrated in the WWDC2022 session Dive Into App Intents I've got that working:

struct OpenEventsList: AppIntent {
    static var title: LocalizedStringResource = "Open Events List"
    static var openAppWhenRun: Bool = true

    @Parameter(title: "Scope")
    var scope: TimeScope

    @Parameter(title: "Publication")
    var publication: PublicationEntity?

    static var parameterSummary: some ParameterSummary {
        Summary("Open \(\.$scope) for \(\.$publication)")
    }

    @MainActor
    func perform() async throws -> some IntentResult {
        // implementation omitted
    }
}

This produces a working shortcut action:

Example shortcut action with parameters populated

In the WWDC talk, the speaker says:

You can also define which parameters show up below the fold and which are hidden. These APIs can do some pretty cool stuff, like varying the summary based on the actual values of any parameter of your intent, using the When and Otherwise APIs, or the Switch, Case, and Default APIs

...but I've not been able to find anywhere that explains these APIs. Apple's docs list some of the protocols involved, but that's it.

I'd like to be able to move the publications option below the fold, so the default parameter summary only includes the time-based option and, if the action box is expanded, the publication option (and other options as I may add later) are revealed.


Solution

  • The Booky example project turned out to be very useful for implementing AppIntents. You can find an example of what you want to do here: Booky at AddBook.swift (L43-L48)

    So what you need is to turn that ParameterSummary into a ParameterSummaryBuilder by adding parameter keypaths inside the brackets:

    static var parameterSummary: some ParameterSummary {
        Summary("Open \(\.$scope)") {
            \.$publication
            // you can add as many as you want
        }
    }
    

    Another good way of implementing your filtering is through an EntityPropertyQuery.

    That will automatically create a Shortcut with the name Find <entity name> that can apply all those filters and ordering and return a list of AppEntities which you can act on.

    If you want to see an example used in production, in Lunar (an app for controlling monitors) I implemented a more complex query for screens which you can find here: alin23/Lunar at LunarShortcuts.swift (L150-L385)

    Here's a screenshot of what that generates in Shortcuts.app:

    screenshot of Shortcuts app showing the Find Screen action implemented in Lunar