In iOS 17 AppIntent, how we can perform dynamic data selection for Widget?

Before iOS17, when we implement "Edit widget" feature with dynamic data, we are using the following ways.

  1. Using an intent definition file
  2. Using an intent extension

Here's the outcome.

  1. A searchable view controller
  2. Multi sectioned data view controller

Here is the implementation

intent definition file + intent extension

class IntentHandler: INExtension, ConfigurationIntentHandling {
    func provideStickyNoteWidgetItemOptionsCollection(for intent: ConfigurationIntent, with completion: @escaping (INObjectCollection<StickyNoteWidgetItem>?, Error?) -> Void) {
        var stickyNoteWidgetItems = [StickyNoteWidgetItem]()
        var archivedStickyNoteWidgetItems = [StickyNoteWidgetItem]()
        
        let allStickyNoteWidgetItems = NSPlainNoteRepository.getStickyNoteWidgetItemsWithoutTrash()
        
        for allStickyNoteWidgetItem in allStickyNoteWidgetItems {
            if allStickyNoteWidgetItem.archived == 1 {
                archivedStickyNoteWidgetItems.append(allStickyNoteWidgetItem)
            } else {
                stickyNoteWidgetItems.append(allStickyNoteWidgetItem)
            }
        }
        
        var sections = [INObjectSection<StickyNoteWidgetItem>]()
        
        if !stickyNoteWidgetItems.isEmpty {
            let section = INObjectSection(title: nil, items: stickyNoteWidgetItems)
            sections.append(section)
        }
        
        if !archivedStickyNoteWidgetItems.isEmpty {
            let archivedSection = INObjectSection(title: "archive".localized, items: archivedStickyNoteWidgetItems)
            sections.append(archivedSection)
        }
        
        let collection = INObjectCollection(sections: sections)
        
        completion(collection, nil)
    }
    
    override func handler(for intent: INIntent) -> Any {
        // This is the default implementation.  If you want different objects to handle different intents,
        // you can override this and return the handler you want for that particular intent.
        
        return self
    }
    
}

However, if I were using AppIntent in iOS17, I can only achieve the following

  1. Not searchable.
  2. Not section-able.

Using AppIntent

    import Foundation
    import AppIntents

    @available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *)
    struct StickyNoteWidgetItemAppEntity: AppEntity {
        static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "StickyNoteWidgetItem")

        @Property(title: "archived")
        var archived: Bool?

        struct StickyNoteWidgetItemAppEntityQuery: EntityQuery {
            func entities(for identifiers: [StickyNoteWidgetItemAppEntity.ID]) async throws -> [StickyNoteWidgetItemAppEntity] {
                // TODO: return StickyNoteWidgetItemAppEntity entities with the specified identifiers here.
                return []
            }

            func suggestedEntities() async throws -> [StickyNoteWidgetItemAppEntity] {
                // TODO: return likely StickyNoteWidgetItemAppEntity entities here.
                // This method is optional; the default implementation returns an empty array.
                return [
                    StickyNoteWidgetItemAppEntity(id: "id0", displayString: "note 0"),
                    StickyNoteWidgetItemAppEntity(id: "id1", displayString: "note 1"),
                    StickyNoteWidgetItemAppEntity(id: "id2", displayString: "note 2")
                ]
            }
        }
        static var defaultQuery = StickyNoteWidgetItemAppEntityQuery()

        var id: String // if your identifier is not a String, conform the entity to EntityIdentifierConvertible.
        var displayString: String
        var displayRepresentation: DisplayRepresentation {
            DisplayRepresentation(title: "\(displayString)")
        }

        init(id: String, displayString: String) {
            self.id = id
            self.displayString = displayString
        }
    }

By using AppIntent, I would like to achieve what is previously achievable using intent defination file + intent extension

Is that ever possible?

Thanks.

In iOS 17 AppIntent, how we can perform dynamic data selection for Widget?
 
 
Q