Confused by appintentsmetadataprocessor errors in Xcode 16?

Development / iOS

I’m currently building a new app for framing screenshots and adding backgrounds for social sharing called Shareshot that is in public Beta. It supplies a bunch of App Intents for Shortcuts integration so that you can batch-frame screenshots.

I tried building it with Xcode 16 betas and found a bunch of confusing build errors for code that builds fine in Xcode 15. You might bump into them too:

2024-07-18 21:33:51.168 appintentsmetadataprocessor[48853:35754477] Starting appintentsmetadataprocessor export
2024-07-18 21:33:51.204 appintentsmetadataprocessor[48853:35754477] error: At least one halting error produced during export. No AppIntents metadata have been exported and this target is not usable with AppIntents until errors are resolved.
error: Found multiple, identical identifiers for query: Query, each identifier must be unique

I was confused by this message. It uses “query” multiple times — I got a lot of them — and initially I just thought this was some straight-up new bug in appintentsmetadataprocessor which is part of the toolchain that processes your App Intents Swift source to extract static elements at build time, to build a JSON file containing metadata about your intents and bundles it into your app.

Eventually I worked out that the capitalised Query was the name of the nested query types used by several AppEntity types in my code:


public struct BackgroundOption: AppEntity, Equatable {    
    public var id: String { value.id }
    public let value: BackgroundInfo
    
    ...
    
    public static var defaultQuery = Query()
    
    public struct Query: EntityQuery {
       ...
    }    
}

I was advised that as of Xcode 16 the type name used for the query type in AppEntity(s) must be “globally” unique and the tooling does not use the fully qualified name of the type if it is nested, contrary to standard Swift scoping. This does seem to work fine in Xcode 15 so it is unclear why this has regressed.

The error was occurring for me as I have several AppEntity that use this same pattern, all using the same locally-scoped Query name — if I had only one it wouldn’t have happened. The workaround is to uniquely name all these nested types, e.g:


public struct BackgroundOption: AppEntity, Equatable {    
    public var id: String { value.id }
    public let value: BackgroundInfo
    
    ...
    
    public static var defaultQuery = BackgroundOptionQuery()
    
    public struct BackgroundOptionQuery: EntityQuery {
       ...
    }  
}

It’s annoying but it’s not a huge problem, if a little confusing at first. It does make me wonder that if I have another global type BackgroundOptionQuery I’ll get other weird build failures if it doesn’t also conform to EntityQuery.

I raised a feedback about this, and received the response that this “Works as currently designed”. So it looks like we need to change our code for Xcode 18. (FB14375756 “appintentsmetadataprocessor fails to process AppEntity with nested query types”).

Hopefully this saves somebody some time.

My Mac History

Apple / Musings
Photo of an original Mac running Through The Looking Glass

Everybody posting their 40th Anniversary of the Mac stories obviously prompted me to write this, which is a roundabout Mac journey. In hindsight the Mac clearly had its effect on me even when I wasn’t using it…

I grew up in Kingston, South West London. Very popular at the time for its affordable/renovatable semi-detached Victorian houses which are now largely unaffordable to normal people. I didn’t know it at the time but I saw what I presume was one of the first ever Macs in the UK, in our house.

Read More

We tried using video ads for Indie App user acquisition. Are TikTok ads a scam?

Business / Making of Captionista
Composite of three iPhones 14 Pro showing screenshots of the app Captionista and its Freestyle feature

Back in late August 2022 we launched version 1.0 of our social video subtitling app Captionista into a crowded segment dominated by huge players including CapCut which is owned by the company behind TikTok. This makes App Store Search ads way too expensive for the keywords we need.

As we were just this week posting videos as part of the marketing, we tried paid video ads to see if that might move the needle. We’ve experimented a little before, but this time we spent more over a shorter period.

TL:DR; Sad trombone sound with a spicy twist.

Read More