Instruction
So far, intents like OpenFavorites or OpenSessionIntent have caused the app to open to present data to the user. If you’ve ever used Siri with CarPlay or a HomePod, you know that visual feedback is either impossible or not desired. Also, opening the app you’re running an intent for will push you out of the current app you’re viewing, which can cause you to lose track of what you were doing.
Luckily, you can adopt some additional protocols and drop one to help with this problem.
Avoiding OpenIntent
Adopting the OpenIntent protocol provides a quick way to force an intent to open the app in question, but you don’t always need to open the app. So you can remove the OpenIntent protocol and leave the AppIntent protocol.
struct GetSessionDetails: AppIntent {
Updating the Return Type of perform
The perform function of an intent is actually quite flexible. It can return anything from an empty result via result() to a complex result that contains the entity, an intent dialog, and a view. To return a complex SessionEntity result like this, the signature of the perform function would read:
func perform() async throws -> some IntentResult & ReturnsValue<SessionEntity> & ProvidesDialog & ShowsSnippetView {
The ProvidesDialog and ShowsSnippetView protocols tell the system that this intent will return the entity in question and a dialog and view to present to the user. In fact, if you forget to specify these protocols and include the view and dialog, the compiler will complain that it was expecting those protocols to be there.
The view is archived like a widget, so developers can use any SwiftUI that widgets can use. In the body of the perform function, the view is initialized for eventual return:
let snippet = SessionSiriDetailView(session: sessionData)
The intent dialog provides information to Siri when it reads information back to you.
let dialog = IntentDialog(
full: """
The runtime reported for \(sessionToGet.name) is \(sessionToGet.sessionLength ?? "no runtime reported") \
and has the following description: \(sessionToGet.sessionDescription ?? "no description provided").
"""
supporting: "Here's the information on the requested session.")
The dialog will read out the full argument if it can’t display a view and only read out the supporting argument when a view can be displayed.
Sharing Data Via Transferable
Core Transferable is a declarative way to describe how your entities can be serialized and deserialized for sharing and data transfer. In iOS, you can now make your app entities transferable. This allows you to use Siri and shortcuts to convert entities to other types and send them to other intents on the system. For example, you could convert your entity into a PDF and email it.
Adopting your existing entities to Transferable can be implemented via an extension. To transfer the entity into a PNG, the extension may look like this:
import CoreTransferable
extension MyAppEntity: Transferable {
static var transferRepresentation: some TransferRepresentation {
DataRepresentation(exportedContentType: .png) { myEntity in
//function to return PNG data here
}
}
}
Other data types can also be included in the closure for TransferRepresentation and as PNGs via a FileRepresentation. They should be declared from highest fidelity, such as Codable, to lowest fidelity, such as plain text.
Now, since you can convert your app’s data into other formats, how can other intents use them? To indicate that an intent can receive data from other intents, use the IntentFile type. For example, here’s a stub of an intent that accepts an IntentFile that can provide an image representation:
struct DisplayToUser: AppIntent {
@Parameter var item: MyEntity
@Parameter(title: "Data to display as image", supportedContentTypes: [.jpeg, .png])
var incomingData: IntentFile
//......
}
The supportedContentTypes part of the @Parameter macro states that this IntentFile must provide either .jpeg or .png formats inside its TransferableRepresentation. While intents can be connected via entities, only those that can be transformed into the required formats will have successful connections for the user.
It’s easy to enhance the user experience when someone uses your app’s entities and intents. Even when the display isn’t showing, or if the device doesn’t have a display like a HomePod, you can provide the necessary information Siri needs to convey the pertinent information to your user. Thanks to Core Transferable now supporting App Intents, you can keep the conversation going with Siri by asking it to send your entities to other app’s intents on the system, which will convert your entity to other formats as required. In the next section, you’ll see how that looks in code with a demo.