Ben Dodson

Freelance iOS, macOS, Apple Watch, and Apple TV Developer

Show Me The Next

An iOS app I worked on for The Browser has gone live in the App Store today; Show Me The Next:

The concept is very simple; an app with curated articles that you read through at random with a simple swipe. No going back, no list no images, no videos, and no tracking; just fast offline access to interesting articles.

I made a quick mockup and then I added some extra features such as the ability to share articles, alter the font size, and change screen brightness1. I also built a simple CMS so that the articles embedded in the app could be updated remotely. The app is built using Swift 2.1, runs on all devices with iOS 9 or above, and is optimised for all the various shapes and sizes including iPad split screens.

As well as completely designing the app and the functionality, I was also asked to design the app icon and logo with a simple single sentence brief: “I admire the art of Mondrian. I took inspiration from the work Composition II in Red, Blue, and Yellow and used the same colours and textures with lines to shape the letters SMTN. It was a fun design experiment and something a bit different for me!

Show Me The Next is a free app and is available on the App Store.

  1. The client did not ask for these additions but I often like to add extra functionality free of charge when I feel it is of benefit to the app. ↩︎

Music Tracker v1.3

I’m very happy to announce that v1.3 of Music Tracker is now available as a free update.

In this version, I’ve focused on speed and stability. The original scanning engine has been completely rewritten from the ground up and now runs faster and for larger libraries than ever before.

Previously, the app would wake up once an hour and have around 30 seconds in order to scan the library, look for additions, changes, and deletions, and then save all of that information locally. This worked great for small libraries on newer devices like the iPhone 6s but didn’t work so well on an iPhone 5s with a library of over 75000 songs. The reason for this is that iOS limits the amount of time an app can run in the background1; if the entirity of the process wasn’t complete in the time allowed, then it would simply fail. This meant that customers with large libraries were typically seeing no updates as the app wasn’t able to get through the entirity of the library within the 30 second window allowed.

To fix this, I rewrote the scanning engine to be faster but to also work in batches. If iOS terminates the Music Tracker process (as it is taking too long) then the current state is saved and will pick up from where it left off the next time the process is restarted2. This means that huge libraries can now be scanned correctly as they are broken up over a few passes rather than trying to do it all at once. A nice side benefit of this is that the app can now handle older hardware3 which previously was too slow to handle even small libraries in a single pass.

In order to accomodate this new multi-pass scanning engine, I’ve also changed the way in which manual updates are performed within the app. Previously you could “pull to refresh” on the main activity page; this gave you a little spinner icon and not much detail as to what was happening. In v1.3, there is a refresh icon in the top right hand corner that will take you to a new page which details exactly what is going on and shows a progress bar so you can see that it is actually working.

If you have already purchased Music Tracker, you should see v1.3 as a free update within the App Store; you can check which version you have installed by going to the settings page within the app. If you don’t yet have Music Tracker, you can get it on the App Store. For more details about the app, you can view the official website at Dodo Apps.

One final thing: on the advice of Dan Counsell, I’ve changed my press media kit to be a standard HTML page with full access to everything the old zip download contained including details of the app, screenshots, icons, and mockup images. This makes it easier for the many iOS journalists who have switched to using something like the iPad Pro as their main work machine which doesn’t handle zip files particularly well. You can check out the online media kit or download the media kit as a zip file.

  1. This is a sensible thing; tasks should not be allowed to run for large periods of time in the background otherwise they’ll kill your battery. ↩︎

  2. Music Tracker typically wakes up every hour to check for changes. ↩︎

  3. Previously the app was only available on devices with a 64-bit chip. Music Tracker now runs on any device capable of running iOS 9.0 which means the iPhone 4s, iPhone 5, and iPhone 5c are now supported. ↩︎

Brapp 2.0

Over the last couple of months, I’ve been working with Brapp on their v2.0 release which adds a ton of new features for video makers, producers, and music lovers.

For video makers, there is a huge improvement to the record and upload flow allowing for studio grade Audio FX such as Pump (compression), EQ, bpm centric Delays, and Reverb1 with adjustments occuring in real time. You can tap on the camera view to adjust exposure and light balance and the recording quality has been improved. Finally, you can now save videos locally complete with a watermark with your name and the beat creator if applicable.

For producers, there is now a systemwide ability to import beats from any app that displays media files. Just tap the share icon and choose the new “Copy to Brapp” option. This will take you to a new editing page that lets you trim the beat to a minute or less in length and add optional fades in or out. The trim page was particularly difficult to build (as you have real time scrubbing and fades, waveform generation, and the ability to move the waveform before you even get to outputting these to a single audio file) but the end result works beautifully.

In addition to these big features, there are 100s2 of smaller changes including:

  • The new profile system makes it possible to hide reposts on a profile so you can just check out their beats and videos.
  • Search is more powerful than ever.
  • It is easier to find new people to follow in the new Explore section.
  • You can now see trending hashtags as they happen in Search > Videos/Beats.
  • Certified. OGs on Brapp will now have the Certified icon by their name3.
  • It is now easier to find beats that are used in videos.
  • It is now easier to save beats you like with the new “Save Beat” button.
  • You now get notifications on reposts, so you can see when your followers react to your reposts.
  • Check out your Mug Shot in Profile > Settings.
  • You can now see all the beats and videos you have Liked in Settings > My Likes.
  • It is now easier to Invite friends to Brapp via Facebook or SMS.
  • Lots of stability and speed improvements.

Finally, previous versions of the app were written in Swift 1.2 using Xcode 6.4 and the iOS 8 SDK. With this build, I migrated it to Swift 2.1 using Xcode 7 and the iOS 9 SDK. This means, among other things, that there is now San Francisco rather than Helvetica Neue throughout!

As ever, Brapp has been a really fun project to work on. I can’t say enough good things about the people behind it and I really believe this app is going to be a big deal. If you haven’t checked it out yet, you can get Brapp for free on the App Store. You can also read about the initial build and release and the v1.1 update last November.

  1. The audio filters were written by David Gibson; I did the integration with the Brapp project and UI. ↩︎

  2. Literally. ↩︎

  3. I am currently certified though I don’t think I will be for long bearing in mind I only have two ‘raps’ and I’m miming in both of them. I did record some sick beats during development but I deleted them pretty quick after recording! ↩︎

Sunday Isn't Special

Last night, the Government lost a vote in the House of Commons to change Sunday Trading Laws in the UK. I don’t usually blog about politics1 but Sunday Trading has been a big issue for me and, as a freelancer, I am incredibly disappointed that there will be no change in this ridiculously outdated law.

As it stands, there are restrictions on trading for shops over 280m². They may only open for 6 consecutive hours between 10am and 6pm2 and there are restrictions on loadings and deliveries. There are some exceptions (such as registered pharmacies, service station outlets, and farms) but pretty much all retail ceases in the UK at 4pm on a Sunday; go to any major supermarket at 3.50pm on a Sunday and you’ll find it packed as people rush to make their purchases before closing time. This is only a fairly recent development though; prior to 1994, the vast majority of shops couldn’t open at all on a Sunday! Thatcher tried to change this in 1986 but was defeated by Labour (protecting workers rights) and her own MPs (concerned with church attendence)3.

In his July budget after the 2015 election, George Osborne announced that the Government wanted to devolve control of Sunday Trading restrictions to local councils so they could decide whether shops could remain open for longer. I personally would have preferred a complete abolition of these rules (as happened during the run-up to the 2012 Olympic Games) but would have been happy with at least some move in the right direction. However, the vote was lost last night with Labour, the SNP, and 27 Conservative MPs voting against the motion.

I find this completely unbelievable in the modern age and massively hypocritical on the part of the SNP when Scotland have no restrictions on Sunday Trading4. Opposition gathered around a “Keep Sunday Special” motto but to my mind there is absolutely nothing special about Sunday. In the past, you could argue on religious grounds but that is irrelevant in the UK today when Atheism has overtaken Christianity5 and the number of actual practicing Christians is on a massive decline (just look at Church attendance).

Commenting on the vote yesterday, Mike Cherry, the policy director of the Federation of Small Businesses, said:

The current system can be seen as a great British compromise which allows families to spend time together, employees to work if they wish to, and provides much needed support for smaller retailers within their communities.

This is absolutely crazy. Families are not spending more time together because of these restrictions and Government should not be restricting free trade on this basis. It also isn’t supporting smaller retailers as large supermarkets have opened small stores on high streets to get around these restrictions. There is already sufficient protections6 against working on Sundays for workers which would not have changed with this bill. All this has done is penalise workers who wish to work longer hours on a Sunday and consumers (many of whom may also work on a Sunday) from making their purchases.

Consider a nurse, police officer, retail employee, or even a freelancer; if they finish their shift at 6pm on a Sunday, then they can’t go and do a weekly supermarket shop because the size of the store is deemed too big. I often work on a Sunday and then have to dash off to the local supermarket at 3.30pm when I realise I haven’t got any food for the evening. Whilst there are smaller newsagents or even smaller versions of supermarkets such as Tesco Metro, these often charge higher prices or don’t have the same amount of choice.

There is also the issue of online shopping; it is perfectly acceptable for somebody to make a purchase online at 7pm on a Sunday night but it isn’t legal for a retailer to sell them something from a physical building larger than 280m² outside of specific hours.

At a time when the economy needs a boost and there are regular complaints about a lack of jobs, it seems to me utterly stupid that there is a law preventing large retailers from creating more jobs. Whilst a separate issue, I’ve never understood why banks aren’t open after around 1pm on a Saturday; there are plenty of people who need work and it seems to me that opening for more hours would solve this.

Whilst I identify as a Conservative, I’m really more of a Libertarian. I believe the Government should have as little to do with people as possible and this is one of those areas where it really shows; a Government should not be able to stop a shop from selling goods at a certain time because of the size of the building it operates from. Scottish politicians should not be able to prevent shops in England from creating more jobs.

Sunday isn’t special. It is no different from any other day, especially if you are a shift worker or a freelancer that works whenever they can.

It is time for Sunday Trading restrictions to be totally abolished.

  1. I have a degree in Politics and have a number of strongly-held views but I don’t like to discuss them on my website which is really to advertise my freelance services. I do tweet about politics regularly though at @bendodson↩︎

  2. Most shops tend to open 10am-4pm although some will be 11am-5pm or even midday-6pm. ↩︎

  3. When I was studying Politics at A-Level, I couldn’t believe that Thatcher’s government had only lost 4 votes in 11 years and one was about the trivial issue of Sunday Trading. ↩︎

  4. Incidentally, I believe this should have been voted on separately to the Enterprise Bill in order to trigger the ‘English Votes for English Laws’ procedure which would have prevented the SNP from having any say over this. ↩︎

  5. The BSA survery in 2014 showed 49% identified as “no religion” with Christianity coming in at 42%. ↩︎

  6. Specifically, staff can “opt out” of working on Sundays even if they had previously agreed in their contract to work on those days. You also can’t be dismissed for not working on a Sunday. The Sunday Working page on the gov.uk website has all of the information. ↩︎

The Divide #9 - Board Game Tangents

Also known as “MithRail: One does not simply ride to Mordor”, the 9th episode of The Divide podcast is now available. This week, we discuss board games including such gems as 1861: The Railways of the Russian Empire, Terra Mystica, Takenoko, and Betrayal at the House on the Hill. We also have time to mention Super Hot, Deadpool, the HTC Vive, and some PC games that I’ve supported on Kickstarter!

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.

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()
    controller.setQueueWithStoreIDs([trackID])
    controller.play()
}

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()
defaults.removeObjectForKey("Username")
defaults.removeObjectForKey("Token")
defaults.removeObjectForKey("SomeSetting")
defaults.removeObjectForKey("FavouriteArtist")
defaults.synchronize()

(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:

NSUserDefaults.standardUserDefaults().removePersistentDomainForName(NSBundle.mainBundle().bundleIdentifier!)
NSUserDefaults.standardUserDefaults().synchronize()

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.

« Older Entries Newer Entries »