Using AssistantEntity with existing AppEntities for iOS17+

Hi, I have an existing app with AppEntities defined, that works on iOS17+. The AppEntities also have EntityPropertyQuery defined, so they work as 'find intents'. I want to use the new @AssistantEntity which is iOS18+ where possible, while supporting the previous versions. What's the best way to do this?

For e.g. I have a 'log' AppEntity:

@available(iOS 17.0,  *)
struct CJLogAppEntity: AppEntity {
    
    static var defaultQuery = CJLogAppEntityQuery()
....
}
struct CJLogAppEntityQuery: EntityPropertyQuery {
        ...
}

How do I adopt this with @AssistantEntity(schema: .journal.entry) for iOS18, while maintaining compatibility with iOS17? I don't want to include two different versions of the same AppEntity. Would it just with with the correct @available annotations on both entities?

Answered by Frameworks Engineer in 891877022

You could add the required properties from the journal.entry schema to your CJLogAppEntity and wrap them around the Property macro. This will allow you to share the same struct between iOS 17 and iOS 18+ while conditionally adding the macro on iOS 18+.

Example:

@available(iOS 17.0,  *)
struct CJLogAppEntity: AppEntity {
        @Property var title: String?
        @Property var message: AttributedString?
        @Property var mediaItems: [IntentFile]
        @Property var entryDate: Date?
        @Property var location: CLPlacemark?
}

@AppEntity(schema: .journal.entry)
@available(iOS 18.0,  *)
extension CJLogAppEntity {}

Note the code above requires you build with the latest SDK while back-deploying it all the way back to iOS 17.

You could add the required properties from the journal.entry schema to your CJLogAppEntity and wrap them around the Property macro. This will allow you to share the same struct between iOS 17 and iOS 18+ while conditionally adding the macro on iOS 18+.

Example:

@available(iOS 17.0,  *)
struct CJLogAppEntity: AppEntity {
        @Property var title: String?
        @Property var message: AttributedString?
        @Property var mediaItems: [IntentFile]
        @Property var entryDate: Date?
        @Property var location: CLPlacemark?
}

@AppEntity(schema: .journal.entry)
@available(iOS 18.0,  *)
extension CJLogAppEntity {}

Note the code above requires you build with the latest SDK while back-deploying it all the way back to iOS 17.

This sample code exhibits the error I mentioned in my comment: 'extension' macro cannot be attached to extension (extension of 'CJLogAppEntity')

import AppIntents
import CoreLocation

@available(iOS 17.0,  *)
struct CJLogAppEntity: AppEntity {
    static var defaultQuery = CJLogEntityQuery()
    let id: String
    static let typeDisplayRepresentation: TypeDisplayRepresentation = "Folder"

    let displayRepresentation: DisplayRepresentation
        @Property var title: String?
        @Property var message: AttributedString?
        @Property var mediaItems: [IntentFile]
        @Property var entryDate: Date?
        @Property var location: CLPlacemark?
}

@AppEntity(schema: .journal.entry)
@available(iOS 18.0,  *)
extension CJLogAppEntity {}

struct CJLogEntityQuery: EntityQuery {
    func entities(for ids: [String]) async throws -> [CJLogAppEntity] {
        return [CJLogAppEntity]()
    }

    func suggestedEntities() async throws -> [CJLogAppEntity] {
        return [CJLogAppEntity]()
    }
}

I also got the same error:

'extension' macro cannot be attached to extension (extension of 'CJLogAppEntity')

Using AssistantEntity with existing AppEntities for iOS17+
 
 
Q