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
@MainActorbeforeperform(), this didn't change anything - I set
static let openAppWhenRun: Bool = trueandstatic 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.semanticContentSearchworked,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
RecipeEntitythroughRecipeIntentValueQuery. - Customer: Picks a yummy recipe to get info on.
- The system: Gets the
idof theAppEntitythe customer tapped on, calls yourRecipeQuerywith that ID - Your app: Returns the
RecipeEntitybased on that ID from theRecipeQuery. If you don't haveIdentifiablestability, things fall apart here because you can't guarantee you're returning the sameAppEntity. - The system: Creates the
OpenRecipeIntentwith theRecipeEntityfrom 5 as itstargetand 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