I'm building a new feature with Visual Intelligence framework. My implementation for IndexedEntity
and IntentValueQuery
worked as expected and I can see a list of objects in visual search result.
However, my OpenIntent
doesn't work. When I tap on the object, I got a message on screen "Sorry somethinf went wrong ...". and the breakpoint in perform()
is never triggered.
Things I've tried:
- I added
@MainActor
beforeperform()
, this didn't change anything - I set
static let openAppWhenRun: Bool = true
andstatic var supportedModes: IntentModes = [.foreground(.immediate)]
, still nothing - I created a different intent for the see more button at the end of feed. This AppIntent with
schema: .visualIntelligence.semanticContentSearch
worked,perform()
is executed
I created a testing project where the issue could be repro. https://github.com/Helen-Xu/kitchen-app-visual-intelligence
Excellent, thank you for that.
With beta 5, I see displayed error message now change to "Search results are limited", but perform method is still not hit and there's no error/logs in console.
This is because your EntityQuery
is returning an empty array:
struct RecipeQuery: EntityQuery {
func entities(for identifiers: [UUID]) async throws -> [RecipeEntity] {
[]
}
However, there's one more important thing you need to do:
struct RecipeEntity: AppEntity, Sendable {
var id: UUID = UUID()
AppEntity
inherits the Identifiable
protocol, and one of the key things about Identifiable
is that it must be a stable identifier, which using the UUID initializer does not provide. This is a common mistake! The stability is foundational to a successful App Intents implementation, because these identifiers are sent to your EntityQuery
implementation above from different invocations around the system — it could be from a Shortcut people have customized to open a specific recipe, or in this circumstance, the customer tapping on one of the Visual Intelligence results to open that specific recipe from the search results. The broad control flow looks like this:
- Customer: Performs visual search and selects your app.
- Your app: Returns
RecipeEntity
throughRecipeIntentValueQuery
. - Customer: Picks a yummy recipe to get info on.
- The system: Gets the
id
of theAppEntity
the customer tapped on, calls yourRecipeQuery
with that ID - Your app: Returns the
RecipeEntity
based on that ID from theRecipeQuery
. If you don't haveIdentifiable
stability, things fall apart here because you can't guarantee you're returning the sameAppEntity
. - The system: Creates the
OpenRecipeIntent
with theRecipeEntity
from 5 as itstarget
and callsperform()
on the intent. - Your app: Your code running in
OpenRecipeIntent.perform()
to configure your app UI to display that recipe.
I hope that clarifies things for you!
— Ed Ford, DTS Engineer