Skip to content
Development

Confirming a MusicKit library write actually landed, without a whole-library scan

By Victor Da Luz
swiftmusickitiosdev-logdeep-cut-atlas

I found a small trust gap in Deep Cut Atlas this week, while working on something unrelated. The app’s “Add to Library” button was reporting success the moment the MusicKit call didn’t throw. It never checked whether the album actually showed up in Apple Music afterward.

That’s not a hypothetical bug. It’s just an unverified assumption sitting in a success path.

Where this came from

I’d just wrapped a spike on something else entirely: a UX annoyance where automating the app on a spare iPhone kept yanking focus away from whatever I was doing on the Mac. Dead end, mostly, but a good one. While closing it out I asked myself a side question: could the app verify its own writes well enough that I wouldn’t need to eyeball Apple Music so often during testing? Turned out the answer was “not really, and here’s why.”

The trap: id-based re-fetching doesn’t work

My first instinct was to copy the pattern already used for playlist writes, which re-fetch after every change. Add the album, then look it up again by id, right?

Wrong, and this codebase had already learned that lesson once. Apple Music’s library and catalog use separate id spaces for the same item. An album you just added to your library does not carry the same id it had in the catalog search result you added it from. I found the exact same gotcha documented in an Apple Developer Forums thread, where a Frameworks engineer confirmed the split is intentional and the id-selection heuristic is nothing third parties should build on.

So a naive “add it, then look it up by id” check would silently never find anything. Worse, it would look correct in code review.

The other trap: whole-library scans are slow

The obvious fallback is to scan the whole library and check if the new album is in there. I’d already measured that cost on a previous pass: about 8 seconds on a real device with a five-thousand-album library. Running that on every single “Add to Library” tap would trade a silent correctness bug for a very loud performance one.

What actually worked

MusicKit’s own documentation on this is thin. Forum answers were vague about what you can filter a library request by. So I stopped guessing and went straight to the source: the framework’s own .swiftinterface file, which ships with every Xcode install and is basically the real API signature, unfiltered by blog posts.

find / -iname "*.swiftinterface" -path "*MusicKit*"

That turned up something the docs don’t spell out clearly: each library-request type exposes a real filter struct, and for albums it includes plain title and artistName strings, filterable directly:

var request = MusicLibraryRequest<Album>()
request.filter(matching: \.title, contains: title)
request.filter(matching: \.artistName, contains: artistName)

That’s a targeted, server-side query, not a scan. It confirms one specific album without walking the whole library. I still do a final exact match against the results, since contains is substring matching, but the expensive part is gone.

Proving it, not just shipping it

Simulator tests don’t touch real MusicKit at all here, so I built for the spare iPhone I use for device testing, drove the actual “Add to Library” flow by hand, and watched the confirmation round-trip against Apple’s servers for real. The button showed “Added to your library” only after the new lookup found it, and the album cleanly disappeared from the source playlist afterward. That’s the difference between “the code compiles” and “the thing actually works,” and on a MusicKit feature the two are not the same claim.

The part worth remembering

When third-party docs and forum answers are vague about a framework’s real capabilities, the actual API surface is usually sitting on disk already, in the SDK you have installed. Reading it directly was faster and more accurate than searching for it.

Related reading