App Intents (Results) Tutorial: A Field Guide for iOS Developers »

Jordan Morgan put together a fantastic guide for App Intents on the Superwall blog – I quoted his Results section here.

From Jordan Morgan, developer advocate at Superwall:

Let’s add a new file, and call it GetCaffeineIntent.swift:

struct GetCaffeineIntent: AppIntent {
	static var title = LocalizedStringResource("Get Caffeine Intake")
	static var description = IntentDescription("Shows how much caffeine you've had today.")

	func perform() async throws -> some IntentResult {
    let store = CaffeineStore.shared
    let amount = store.amountIngested
    return amount
	}
}

This has all of the three things we mentioned above:

  1. It has a title (“Get Caffeine Intake”).
  2. A description of what happens when we use it (“Shows much much caffeine you’ve had today.”)
  3. And, an implementation of that action, vended via the perform function.

However, if we build and run — we’ll get a compiler error:

`Return type of instance method 'perform ()' requires that 'Double' conform to 'IntentResult'`

Looking at the return type, it’s some IntentResult. This is critical to understand to avoid a lot of undue frustration with App Intents. You always return some form of an IntentResult. For example, if your intent just does an action, and has nothing of value to say about that action — you can simply return .result(). You don’t ever return some primitive or domain specific type like we’ve done above.

Ours, though? It would be useful to tell the user how much caffeine they’ve had and return the actual amount, so change the return type to mark the intent to return two things:

An actual Double value of how much caffeine has been consumed.

And, some dialog to speak out their caffeine for the day.

So, instead of some IntentResult, here’s what we need:

func perform() async throws -> some IntentResult & ReturnsValue<Double> & ProvidesDialog {
	
	let store = CaffeineStore.shared
	let amount = store.amountIngested
return .result(value: amount,
               dialog: .init("You've had \(store.formattedAmount(for: .dailyIntake))."))
}

Each intent’s return type needs to start with some Intent opaque return type, but from there we can also include more specific types. Here, we’ve noted that we return a double value and speak out dialog.

Developers should read the entire post, but I highlighted this portion because it’s fairly poorly documented and incredibly important.

Jordan also covers basic Intent setup, more on the Entity front, and using Siri Tips and Shortcuts Links to bring more visibility to your actions.

Read the full post on Superwall’s blog.

 

Posts You Might Like

New App Intents and Apple Intelligence Consulting Availability
Get your app ready for Apple Intelligence with App Intents consulting — from audits to full integrations with Siri, Spotlight, and Shortcuts.
Here are Apple’s WWDC25 Developer Sessions on the Foundation Models Framework
Discover WWDC25’s Machine Learning & AI sessions for developers—Foundation Models, MLX, Vision, and SpeechAnalyzer, all focused on private AI
Ulysses adds Find Sheet, Find Group actions for Shortcuts; Substack support »
Ulysses has expanded their App Intents support in version 39 with Find, Import File, and Search actions – plus support for Spotlight on Mac.
How to integrate Siri and Apple Intelligence into your app to query onscreen content »
Jordan Morgan has shared another excellent App Intents guide, this time setting developers up so users can query on-screen content using Apple Intelligence.