Ben Dodson

Freelance iOS, Apple Watch, and Apple TV Developer

Storefront Additions: A simple way to convert SKCloudServiceController store identifiers into country codes

In my article a few days ago, I noted that SKCloudServiceController would give you a storefront identifier but that there was very little information about how to use that identifier when using the iTunes Search API. As it turns out, Apple do provide a list of store identifiers with their respective ISO country codes on their iTunes Affiliate Links website - a big thank you to Loreto Parisi for directing me to it.

In order to make things a bit easier for other developers, I’ve put together a simple class and plist file that will automatically return a country code for the current user’s store. It’s incredibly simple:

StorefrontAssistant.countryCode { (countryCode, error) in
    if let error = error {
        NSLog("Error: \(error)")
    if let countryCode = countryCode {
        NSLog("Country code: \(countryCode)")

Storefront Assistant will automatically request permissions to access the Media Library and then fetch the current storefront identifier for the logged in user. If there are any issues (i.e. permissions denied, no connectivity, country code can’t be found) then an NSError will be returned.

Once you have the country code, you can then use the iTunes Search API to search for tracks in the correct country; these can then be used with MPMusicPlayerController for immediate playback or MPMediaLibrary for saving to the user’s Media Library.

The full code is available on GitHub.

Update, 10th Mar 2016: Loreto Parisi has put together some code in order to provide this list as a JSON file instead of a plist; he also has a Node JS implementation to scrape this information regularly from the iTunes Affiliate Link Website. Check it out on GitHub.

Update, 31st Mar 2016: Thanks to Matt Abras it turns out that the above code isn’t necessary; you can just use the undocumented s=143444 instead of country=gb when using the iTunes Search API.

Details on the iOS 9.3 Media Library additions

UPDATE: Thanks to my raising this privacy concern, Apple have resolved this issue as of iOS 10. I’ve left the old post below for posterity.

Due to my article on music library security on iOS, I’ve found myself in the position of being misquoted or misunderstood on sites such as AppleInsider (mainly in the comments) with regards to the new media library APIs in iOS 9.3. This article is intended to clear up some misunderstandings that people have about these new APIs.

In iOS 9.3, there are several additions to the music library. Indeed, it is the first item listed in the What’s New in iOS 9.3 developer document:

New methods in the Media Player and StoreKit frameworks let you add an Apple Music track to the music library and play it. First, use the SKCloudServiceController API to determine the current capabilities, such as if the device allows playback of Apple Music catalog tracks and the addition of tracks to the library. Then, you can use the MPMediaLibrary method addItemWithProductID:completionHandler: to add a track to the library and the MPMusicPlayerController method setQueueWithStoreIDs: to play a track.

Firstly, the StoreKit framework has been updated to include an SKCloudServiceController which basically gives an app the opportunity to request access to a user’s media library and to check if they have the ability to stream Apple Music tracks and / or add those tracks to their iCloud Music library.

Next, MPMusicPlayerController has been updated with a new method named setQueueWithStoreIDs which allows you to basically hand over an array of Apple Music identifiers and have those play instantly in the Music app without leaving your own app. Interestingly, this allows you to Rickroll someone in just a few lines of code:

func play() {
    let trackID = "255991760" // use 302053341 in USA, 255991760 in UK
    let controller = MPMusicPlayerController()

This API, whilst interesting, has a few issues; the identifiers for music tracks are different for each country so a US track will not play on a UK Apple Music account1. There is also no error handling so it’ll just silently fail if you give it an incorrect identifier or one from the wrong store.

The final new addition is to MPMediaLibrary and is a method named addItemWithProductID:completionHandler:. This allows you to add an Apple Music track to the user’s library as long as they gave permission via the SKCloudServiceController and they have a valid Apple Music account. I had some issues getting this working on an iPhone 5c but it worked just fine on an iPad Pro leading me to think this may be an API limited to 64-bit devices (although this is still in beta so that may change). However, the API does not allow you to add MP3s to your library or import Spotify tracks or anything like that; it is just a way to add Apple Music tracks to your library. Why is that useful? The scenario I envision is that it is for apps like Shazam that identify music and then traditionally give you a link to go and see it in Apple Music or the iTunes Store. With this new API, those apps can now add a button such as “add this track to your library?” which will allow them to automatically add the Apple Music track to the media library.

The new APIs do not do any of the following things:

  • They do not allow apps to add music to your library if you are not using Apple Music
  • They do not allow apps to add music to your library that is not available on Apple Music
  • They do not allow apps to delete music from your library
  • They do not allow apps to edit metadata on any music in your library (i.e. changing title, artist, genre, rating, artwork)

Crucially, and linking this back to my previous article, this new permissions system is only for the new “add Apple Music tracks to your library API”; apps do not require permission to scan through your library. I’m still hopeful this will be addressed as at present the ‘Privacy’ settings screen in iOS 9.3 is incredibly misleading:

I take serious issue with the phrase “Apps that have requested access to your media library will appear here” because it makes it sound like apps require permission to access your library which is just not true. My Music Tracker app continues to work unimpeded on iOS 9.3 with no need to request access and, as demonstrated above, you can start playing streamed music in the Music app without authorization. This is all true as of iOS 9.3 beta 4 so hopefully it may get resolved before the final version of iOS 9.3 is released next month.

(Update: This was not resolved in the public version of iOS 9.3)

If you have any queries about how these new APIs work or how they will or won’t affect your media library, please feel free to contact me.

  1. There is a new API to give you a storefront identifier (mine is "143444,29") but I'm not sure how you translate to a single language like "gb" for use with the iTunes Search API - if anyone can shed some light on that, please let me know!

    Update, 10th Mar 2016: Thanks to Loreto Parisi for making me aware of the iTunes Affiliate Link website which contains a full list of the store identifiers and their respective ISO country codes which can be used with the iTunes Search API. I’ve put together a simple class to take care of this automatically.
    Update, 31st Mar 2016: Thanks to Matt Abras it turns out that the above code isn’t necessary; you can just use the undocumented s=143444 instead of country=gb when using the iTunes Search API↩︎

The Divide #8 - Drunkstarter: A discussion on crowdfunding

The 8th episode of The Divide podcast is now available in which we discuss crowdfunding1 along with some of our favourite Kickstarter campaigns. We also check in on Mass Effect 4 pricing, dissect the iPhone Code 53 issue, and wonder if Nicolas Cage movies can fix online dating.

You can get The Divide from these fine outlets:

Don’t forget to leave a review on iTunes and follow us on Twitter via @PodcastDivide.

  1. Chris hasn’t tried it, John loves it, and I hate it. ↩︎

Music Tracker v1.1 and Pocket Rocket v1.1 Released

Last week, version 1.1 of both Music Tracker and Pocket Rocket were released in the App Store.

The main new feature for Music Tracker v1.1 is native support for iPad. This includes not only the iPad Air and iPad Pro, but also all of the various split-screen modes that can be applied in both portrait and landscape. This release also includes landscape support for the iPhone. There were also a few minor bug fixes.

I’m aware that a few people with large libraries (anything over ~25000 tracks) are experiencing some performance issues which can cause the automatic tracking to fail; a new update is under development to fix that. If you have a large library and would like to test that release, please let me know.

Pocket Rocket v1.1 adds a few features that were requested from existing customers. These include the ability to see the total number of unread articles on the app icon and using Background App Refresh to keep that count up-to-date. There are also a few bug fixes (including a big one that crashed the app with certain query strings in URLs) and a 3D Touch Quick Action (for iPhone 6s) so you can see when the articles were last updated.

If there are any features you’d like to see added to either Pocket Rocket or Music Tracker, please get in touch.

Deleting all NSUserDefaults with Swift

NSUserDefaults is likely one of the most used APIs on iOS providing a quick and easy way to store basic configuration and settings. However, these can quickly mount up and you’ll typically end up with something like this in your project within a logout method:

let defaults = NSUserDefaults.standardUserDefaults()

(Note: you should never store secure information like a password or API token in NSUserDefaults; that’s what the Keychain is for. You should probably also use static constants in a config file for your keys but this will do for a demonstration)

The problem with something like this is that you have to remember to go and add an extra removeObjectForKey whenever you add a new setting and this can be easily forgotten and lead to settings being shared between different user accounts. I’ve definitely been guilty of doing this in the past and, whilst working on an update to Pocket Rocket, I found that this can be much simpler:


This will clear all of the NSUserDefaults that have been set by your code leaving you with a fresh slate just as if the app had been deleted and reinstalled. You don’t need to update your logout method whenever a new setting gets added and you can be sure that everything is being reset in full.

Update: a few people have asked why I perform NSUserDefaults.standardUserDefaults().synchronize() as this should happen automatically. The key word here is should; since iOS 7, NSUserDefaults do not get written to disk as frequently as previously (i.e. when going into the background). With the addition of things like watch extensions, widgets, and keyboards that can all access a shared NSUserDefaults, I find it is always best to perform a sync (which ensures the data is written to disk immediately) as then none of the other aspects of your app or extensions will access invalid data. It doesn’t add any significant performance overhead in my experience but can save you from embarrassing bugs.

Calm Radio for iOS

I’m happy to announce that the new iOS app I built for Calm Radio is now live in the App Store.

Last month, I announced the launch of the Apple TV app for Calm Radio; the client was so pleased with the end result that they commissioned me to also rebuild their existing universal iOS app. This is a special project for me as I didn’t only build the app from scratch, but I also designed it fully. With the Apple TV app, I took design cues from the stock apps provided by Apple such as Movies and TV Shows; with the iOS app, I’ve taken inspiration from that design and kept the vibrant backgrounds created by blurrding the rich artwork that was available for each channel.

As well as the standard playback and support for up to 3 ambient channels, the iOS app adds many features not found in the Apple TV app; an alarm clock, sleep timer, ability to skip track, favouriting channels, and full support for streaming to AirPlay and Chromecast devices. I also included support for 3D Touch by making use of Quick Actions to show your most recently listened to stations directly on the app icon. In addition, the app inherits many new features that were first designed for the Apple TV app such as video backgrounds.

One of the things I’m most proud of is the adaptability of the UI. The app can run in an incredible 20 different sizes and orientations1 based on the various iPhone and iPad sizes, portrait and landscape support, and the new split-screen modes available to more recent iPads.

I’m honoured that my work on the Apple TV app was so well received that I was able to bring the same design and functionality to the Calm Radio iOS app. You can download Calm Radio from the App Store or learn more on their website. The app is free although certain features are limited to paid subscriptions.

  1. The full list is iPhone 4s (portrait), iPhone 5 (portrait), iPhone 6 (portrait), iPhone 6 Plus (portrait), iPhone 4s (landscape), iPhone 5 (landscape), iPhone 6 (landscape), iPhone 6 Plus (landscape), iPad Mini (portrait), iPad Mini (landscape), iPad Air (portrait), iPad Air (landscape), iPad Air (30% width split-screen portrait), iPad Air (25% width split-screen landscape), iPad Air (50% width split-screen landscape), iPad Pro (portrait), iPad Pro (landscape), iPad Pro (30% width split-screen portrait), iPad Pro (25% width split-screen landscape), and iPad Pro (50% width split-screen landscape). ↩︎

The Divide #7 - Mind Missiles and The Internet of Stuff

The 7th episode of The Divide podcast is now available. Chris, John, and myself discuss a number of cool pieces of internet enabled hardware you can go and buy today. We’ll give examples of how to connect your home together with IFTTT, HomeKit, and devices like the Arduino and I spend a lot of time discussing my beloved Hue light bulbs. It turns out that John wants more Raspberry Pi’s in his life, I want the new Tesla update, and Chris has an interesting idea for a TV show…

You can get The Divide from these fine outlets:

Don’t forget to leave a review on iTunes and follow us on Twitter via @PodcastDivide.

Music Tracker

I’m very happy to announce that my latest self-published app, Music Tracker, is now available on the App Store.

Music Tracker is an iPhone app that keeps an eye on your music library and monitors additions, deletions, and any changes to your songs. With streaming becoming more popular, it is very easy for song metadata to change or for songs to disappear as licensing deals expire; with Music Tracker, you will always know when something in your library changes whether it was by you, a family member, or your streaming service.

I came up with the idea for Music Tracker after noticing that the amount of songs returned by iTunes was different to that in my Music app on my iPhone. This was due to a song I had in Apple Music that was no longer available in the UK and so had been automatically deleted from my iPhone and greyed out in my iTunes library on my mac. After a quick prototype, I had an app that would run on my phone and keep track of any deletions and additions so I’d be alerted if Apple altered my music. After a few weeks, there were several changes picked up by my app including a few songs that were just plain deleted and some that were completely altered (i.e. I had a studio recording of Uptown Girl by Billy Joel that was switched for a live recording - with Music Tracker, I could see this change and switch it out for a studio recording from a different album).

In my original prototype version, I actually exported the entire music library as a JSON file and uploaded it to GitHub1. However, to make it work natively on the device without an internet connection I made use of the Realm mobile database which is fantastic and insanely fast. The entire process of extracting the metadata from your library, comparing it against the existing dataset saved in Realm, and then creating a log of changes, additions, and deletions takes around 2.2 seconds on a library of 10000 songs2 and allows a full activity feed showing changes on a granular level:

From a technical point of view, there are 3 different ways in which Music Tracker can update depending on the options you choose during setup:

  1. If you enable push notifications, then a silent push notification3 will be sent to your device once an hour that wakes up the app in the background and checks for any changes. This typically lasts around 2 seconds on a standard library of 10000 songs and in my opinion is a pretty clever way of getting around the fact that you can’t schedule background tasks on iOS.

  2. If you don’t enable push notifications, the app will make use of Background App Refresh (limited to once per hour) to do an update in the background in a similar way to the silent push notifications. These typically fire when the phone is connected to WiFi and a power source but mileage will vary depending on what apps you have installed (and for that reason I recommend the silent push option).

  3. If you go into iPhone settings and disable Background App Refresh, then the only way to update the library is to open the app and pull to refresh (or use the 3D Touch Quick Action if you have an iPhone 6s / 6s Plus).

Before finishing the app, I added full 3D touch support (both quick actions and “Peek and Pop”) and a basic Apple Watch app that allows you to see how many songs are in your library, and how many songs have been added, changed, or deleted today (along with name and artist of those tracks). In addition, there is a glance providing this information in a single screen and text-based complications for the Utility, Modular, and Mickey Mouse faces with a quick summary of your library today.

This was the first project in which I used Fastlane for the provisioning profile, certificate generation, push notification setup, TestFlight, and iTunes Connect submission and I’d highly recommend it; so much simpler than doing those things manually! The TestFlight beta test was also well worth doing as with something like this I could only really test on a handful of devices but I needed to see load times on other devices and larger libraries - a big thank you to all of my beta testers. Once the app was submitted, I was honestly expecting the app to be rejected but it went straight through review without a problem4.

The final thing to mention is an issue of privacy. I’m very proud of the fact that no data leaves your device from this app5 and I have a simple and transparent Privacy Policy6. However, I do think it is bizarre that iOS does not require any permissions dialogue when accessing the music library. I wrote a post about this last week detailing this big privacy flaw and I’ve submitted a bug report to Apple (rdar://24168798) in the hope that a standard privacy alert will be added in iOS 10.

You can download Music Tracker on the App Store (priced at $0.99 / £0.79) and learn more about it on my Dodo Apps website. If you are interested in reviewing Music Tracker or writing an article surrounding the privacy issue, you may can download the media kit which contains more information along with screenshots, mockups, and app icons.

If you find Music Tracker useful, I’m always grateful for a review on the App Store. If you run into any issues or have feature requests, you can contact me directly.

  1. You can see how this looked by seeing the commit log at ↩︎

  2. Your mileage may vary depending on how many songs you have in your library and what device you are using; it’s obviously faster on an iPhone 6s than a 5s. The app requires a 64-bit processor due to this and so will not run on the iPhone 4s, 5, or 5c. ↩︎

  3. The key part here is “silent”. These notifications wake up your phone and do some processing but you don’t receive any alerts, sounds, or badge icon updates unless you specifically opt-in to the “Summary Notification” within the settings panel (and that sends a simple text alert once per day if your library changed on the previous day). ↩︎

  4. Although v1.0.1 was “In Review” for 3 days before approval. ↩︎

  5. There are no analytics or tracking of any kind. I did use Parse during the beta test in order to save a basic log of library sizes and processing times but that has all been removed for the App Store version and can be checked with a network debugger like Charles Proxy↩︎

  6. Summary: I really don’t want your data. ↩︎

Your music library is a security and privacy risk on iOS

UPDATE: Thanks to my raising this privacy concern, Apple have resolved this issue as of iOS 10. I’ve left the old post below for posterity.

Over the years Apple has put a lot of effort into making iOS secure and privacy focussed. You are prompted with dialogue boxes whenever an app tries to access your contacts, calendars, photos, or location and you need to confirm that you want to receive notifications. However, whilst developing Music Tracker1 I discovered that there is no privacy prompt when a developer tries to access your library. In fact, they can access all of your music data as simply as this:

let query = MPMediaQuery.songsQuery()
if let items = query.items {
    for item in items {
    	NSLog("Title: \(item.title)")

That’s just a basic example that’ll output the title of every song in your library but there is a lot of danger in that. This process happens completely silently and in my tests I was able to loop through a library of 10000 songs, put all the metadata in a JSON file2, and upload it to a server in under 2 seconds!

But why is this a security or privacy risk? Off the top of my head, I can think of two massive risks:

  1. Your library says a lot about you3. If an advertising company was able to get a complete list of your music library (along with changes to it over time) then they could very easily target you with specific ads. Added a lot of Taylor Swift recently? Here are some ads relevant to that.

  2. When iOS first came out there was something called a UDID which basically identified your device uniquely. This was used by marketers to track you across multiple apps and build up a profile. This was stopped by Apple a few years back and replaced with an advertising identifier which you can turn off and which can only be used between apps from the same company (where they are probably already tracking you). However, with a full music library, it would be fairly easy to track someone across multiple apps as periodic snapshots could be compared on a server.

I’ve no idea if apps are already doing this in the background silently but it is something that shouldn’t be able to happen. To that end, I’ve filed a bug report with Apple (rdar://24168798) to ask that they implement the same privacy controls that they do for contacts, calendars, photos, and location; a prompt when an app tries to access this data and the ability to grant or reject that permission through the system wide settings. Hopefully this is something Apple will implement in iOS 10 – if you’d like to see this happen, please duplicate bug 24168798 in the Apple Bug Reporter as that is the best way to bring it to their attention.

Update, 20th Jan 2016: A few people have pointed out that the first beta of iOS 9.3 does have a new privacy setting for “Media Library”. However, this does not stop the above line of code and read-only access to your library; instead, it is part of a new feature that allows for apps to add songs to your iCloud Music Library but requires your permission to do so. Apps that use the MPMediaQuery above won’t even appear in the Media Library permissions page to disable so this is not the solution some think it is.

Update, 23rd Feb 2016: Several articles are now linking to this and picking up on my comments about iOS 9.3 above and horribly misunderstanding what those new APIs do. I’ve published a new article detailing exactly what the new APIs in iOS 9.3 add to the music library (and what they don’t add). As of iOS 9.3 beta 4, there are no privacy controls on scanning your music library and it still works exactly as I’ve described above.

Update, 25th March 2016: With the public release of iOS 9.3, this issue is not resolved as per my post last month.

Update, 13th June 2016: Thanks to my raising awareness of this issue, iOS 10 (released in beta for developers today) has added full privacy controls for read access to the local media library. I’ll write up a post in the future about how the new APIs work (done).

  1. Available on the App Store. Find out more at Dodo Apps↩︎

  2. I uploaded it to GitHub so you can get a feel for how big a file it generates in that small amount of time. ↩︎

  3. Let’s not read into what C’est La Vie by B*Witched means about me… ↩︎

Munchkin Report

I’m very pleased to announce that another client app I developed recently has gone live in the App Store; Munchkin Report for iPhone.

Munchkin Report is an online service that helps you track your child’s moments, big and small. From her first steps to yesterday’s nap schedule, Munchkin Report captures memories, keeps parents and caregivers in-sync, and helps you make informed decisions.

It was a real pleasure to work on this app as I was able to work in an incredibly efficient way. The client provided me with a complete API (including full documentation1) and some static wireframes; I was then left to my own devices for a couple of weeks and given creative freedom to build my own design and tweak the UX as I saw fit. In the end I settled on an iOS 7 style minimal design which puts the important information up front and uses bold colours for UI controls.

The design is optimised for all four sizes of iPhone from the tiny iPhone 4s to the massive iPhone 6s Plus. It was written in Swift 2.1 and runs on iOS 9.0 and greater.

I had just received my iPhone 6s when I started the project so as a little extra2 I added 3D touch quick actions so you can quickly get to the log actions from the home screen. There is also “Peek and Pop” integration throughout.

I’m really pleased with the way this app turned out and I think it’ll be a great resource for childcarers and parents. Munchkin Report is free but does require an account from (free trials are available). You can download Munchkin Report from the App Store or learn more on their website.

  1. You’d be surprised how rare that is! ↩︎

  2. One of the main reasons I do client work is so I can experiment with new APIs I wouldn’t necessarily use if I was just doing my own apps. I often add features for free to client apps to give me a bit more experience using a certain framework. ↩︎

« Older Entries Newer Entries »