With iOS/Apple AppIntents, your iOS app can declare AppIntents, which users can use from the Shortcuts App to use as steps in their own manually/Siri/etc triggered Shortcuts, but also from their own Automations (when a certain event occurs, run a series of AppIntents or a specific Shortcut etc), to run code you’ve defined.
If you want to dynamically trigger follow up AppIntents, your User has to use the if logic to wrap the AppIntent as they use it to make a Shortcut.
Instead, is it possible to dynamically chain/trigger different AppIntents, using OpensIntent?
I tried it. But I get this compiler error. I’m new to Swifts type system, and I cannot figure whether it’s possible to somehow wrap NextAppIntent and OtherNextAppIntent in an enum or protocol or some other language feature to solve this.
ERROR: Function declares an opaque return type 'some IntentResult & ReturnsValue<String> & OpensIntent', but the
return statements in its body do not have matching underlying types
Error caused due to NextAppIntent, OtherNextAppIntent have different type
Is it possible to solve this compiler error and therefore achieve dynamically chaining different AppIntents with OpensIntent? (I would guess that this compiler error is not solvable and represents it is not intended to be able to dynamically chain different AppIntents with OpensIntent)
E.g.
First Intent
@available(iOS 16.0, *)
struct SomeAppIntent: AppIntent {
// Arbitrary parameter
@Parameter(title: "App")
var app: String
@MainActor
func perform(
) async throws -> some IntentResult & ReturnsValue<String> & OpensIntent {
// use api to figure some condition
var some_condition: Bool = some_api.check_some_thing()
if (some_condition) {
return .result(
value: app,
opensIntent: NextAppIntent(app: $app)
)
} else {
return .result(
value: app,
opensIntent: OtherNextAppIntent(app: $app)
)
}
}
}
// diff file
@available(iOS 16.0, *)
struct NextAppIntent: AppIntent {
// Arbitrary parameter
@Parameter(title: "App")
var app: String
static var openAppWhenRun: Bool = true
@MainActor
func perform(
) async throws -> some IntentResult {
...
}
}
// diff file
@available(iOS 16.0, *)
struct OtherNextAppIntent: AppIntent {
// Arbitrary parameter
@Parameter(title: "App")
var app: String
static var openAppWhenRun: Bool = false
@MainActor
func perform(
) async throws -> some IntentResult {
...
}
}
Q: Why not just dynamically invoke the functionality all in the first app intent?
A: Sometimes you might need the functionality to be separated into separate app intents i.e. static var openAppWhenRun: Bool = false|true
Q: What about just using throw error or exit(0) to prevent progression to next app intent?
A: It is a hacky workaround, but the user will always be notified that an error occurred AFAICS. You also might not be able to express the conditional logic you want.