AppIntent Parameter Argument List of Apps

I'm currently exploring how to implement the AppIntent parameter with a list of apps similar to what's shown in the screenshots provided below:

I'm particularly interested in how the searchable list of apps is implemented. My current approach involves creating an enum for the apps, but it lacks searchability and requires manual addition of each app.

Does anyone have an idea on how this functionality might be implemented? It appears that the searchable list might be a native Apple view, but I haven't been able to find any documentation or resources on it. Any insights or pointers would be greatly appreciated!

Accepted Reply

I found the solution, with an EntityQuery you can achieve the expected result. The con is that you actually need to have a list of Apps for it to work. Here is the code:

Step 1: Create an AppEntity

struct EntityName: AppEntity, Identifiable {
  var id = UUID()
  let url: String
  let name: String

  var displayRepresentation: DisplayRepresentation {
    DisplayRepresentation(title: "\(name)")
  }

  static var typeDisplayRepresentation: TypeDisplayRepresentation = "App"
  static var defaultQuery = AppQuery()
}

Step 2: Create AppQuery

struct AppQuery: EntityQuery, EntityStringQuery {
  func entities(for identifiers: [UUID]) async throws -> [EntityName] {
    identifiers.compactMap { id in
      apps.first { $0.id == id }
    }
  }

  func entities(matching string: String) async throws -> [EntityName] {
    return apps.filter { $0.name.localizedCaseInsensitiveContains(string) }
  }

  func suggestedEntities() async throws -> [EntityName] {
    // assuming you defined apps somewhere
    return apps
  }
}

Step 3: Use Entity in AppIntent

struct SomeIntent: AppIntent {
  static let title: LocalizedStringResource = .init("T", defaultValue: "Some Name")
  static var openAppWhenRun: Bool = false

  @Parameter(title: "Select App Here!")
  var selectedApp: EntityName

  @MainActor
  func perform() async throws -> some IntentResult & OpensIntent {
      // handle
  }
}

Hope, this may help someone!

Add a Comment

Replies

I found the solution, with an EntityQuery you can achieve the expected result. The con is that you actually need to have a list of Apps for it to work. Here is the code:

Step 1: Create an AppEntity

struct EntityName: AppEntity, Identifiable {
  var id = UUID()
  let url: String
  let name: String

  var displayRepresentation: DisplayRepresentation {
    DisplayRepresentation(title: "\(name)")
  }

  static var typeDisplayRepresentation: TypeDisplayRepresentation = "App"
  static var defaultQuery = AppQuery()
}

Step 2: Create AppQuery

struct AppQuery: EntityQuery, EntityStringQuery {
  func entities(for identifiers: [UUID]) async throws -> [EntityName] {
    identifiers.compactMap { id in
      apps.first { $0.id == id }
    }
  }

  func entities(matching string: String) async throws -> [EntityName] {
    return apps.filter { $0.name.localizedCaseInsensitiveContains(string) }
  }

  func suggestedEntities() async throws -> [EntityName] {
    // assuming you defined apps somewhere
    return apps
  }
}

Step 3: Use Entity in AppIntent

struct SomeIntent: AppIntent {
  static let title: LocalizedStringResource = .init("T", defaultValue: "Some Name")
  static var openAppWhenRun: Bool = false

  @Parameter(title: "Select App Here!")
  var selectedApp: EntityName

  @MainActor
  func perform() async throws -> some IntentResult & OpensIntent {
      // handle
  }
}

Hope, this may help someone!

Add a Comment