Open Intent in iOS 26
This post is brought to you by Sentry, mobile monitoring considered "not bad" by 4 million developers.
While working on Alyx and its (over 40!) Siri Shortcut actions, I came upon the need for an AppEntity
to launch the app. In the past, I had similar intents for Elite Hoops:
struct OpenTeamIntent: AppIntent {
static var isDiscoverable: Bool = false
static var title: LocalizedStringResource = "Open Team"
@Parameter(title: "Team")
var team: TeamEntity
@Dependency
var deepLinker: DeepLinker
init(team: TeamEntity) {
self.team = team
}
init() {}
@MainActor
func perform() async throws -> some IntentResult {
deepLinker.selectedCourtID = team.id
return .result()
}
}
Turns out, doing it this way is🥁….
Wrong!
There’s an intent type just for this type of thing, called OpenIntent
. So, I adopted that correctly:
struct OpenTeamIntent: OpenIntent {
static var isDiscoverable: Bool = false
static var title: LocalizedStringResource = "Open Team"
@Parameter(title: "Team")
var target: TeamEntity
@Dependency
var deepLinker: DeepLinker
init(target: TeamEntity) {
self.target = target
}
init() {}
@MainActor
func perform() async throws -> some IntentResult {
deepLinker.selectedCourtID = target.id
return .result()
}
}
But wait! It’s actually even easier than that! I don’t even need my own navigation class to do this anymore. Enter iOS 26 variant:
import AppIntents
import CaffeineKit
struct OpenDrinkIntent: OpenIntent {
static let title: LocalizedStringResource = "Log Matched Drink"
@Parameter(title: "Drink", requestValueDialog: "Which drink?")
var target: CaffeineDrinkEntity
func perform() async throws -> some IntentResult {
return .result()
}
}
#if os(iOS)
extension OpenDrinkIntent: TargetContentProvidingIntent {}
#endif
That’s it! Then, in your app in some view, there’s a modifier to handle it:
SomeView()
.onAppIntentExecution(OpenDrinkIntent.self) { intent in
AlyxLogs.general.info("Opening drink intent: \(intent.target.name)")
openTheThing()
}
To recap:
- Adopt
OpenIntent
- Provide a
target
(yes, it MUST be named exactly that) of one of yourAppEntity
types. - Add the
TargetContentProvidingIntent
conformance to it. - And use the
onAppIntentExecution
modifier.
That’s an API at play I used with Visual Lookup support, by the way:
Until next time ✌️