Ben Dodson

Freelance iOS, Apple Watch, and Apple TV Developer

Great British Bee Count 2016

Last year I worked on rebuilding the Great British Bee Count iPhone app for Friends of the Earth. Today, an updated version of the app has gone live to support this years count which runs from 19th May until 30th June 2016:

There are several updates including a redesigned bee picker, more details of the bees, and a list of plants suitable for attracting bees sponsored by Waitrose. The app is also now universal with support for both the iPhone and iPad1.

You can check out the Great British Bee Count on the App Store (it’s free) or learn more about the bee cause.

  1. This came about due to a restriction in the App Store. If you search for an iPhone-only app on the iPad, you have to manually select “iPhone-only” when searching which nobody in their right mind does (as iPhone apps run on iPad just fine in a scaled mode). To make it so that searching “Great British Bee Count” on the iPad App Store would show the app, it had to be a universal app but the client didn’t want to have a custom design for the iPad but continue to use the iPhone scaling. There isn’t an elegant way to do that (as turning on Universal mode will cause AutoLayout to treat the iPad like an iPad) so I solved this by writing a custom view controller that would take the iPhone 4s XIB files and then simply scale them upwards with an affine transform. I also added an extra border on the sides that matches the yellow background to avoid the black boxing that the previous version had. This works great on all iPads (including the iPad Pro) but the text on some items is quite blurry on the non-retina iPad 2 due to a bug within the Apple Frameworks; it’s intelligent enough to use the retina imagery so that images look smooth but not on text apparently. ↩︎

Using a physical button (Flic) with HomeKit scenes and triggers

When I started out as a web developer I was fascinated by APIs; the ability to hook into other data sources or update other applications from my own had huge potential that is finally being realised with the Internet of Things1. It is now possible to write apps that interact with physical objects via such things as IFTTT or dedicated APIs for devices like the Philips Hue. I’ve personally been very interested in the HomeKit initiative from Apple although it hasn’t really taken off yet.

Whilst I have a lot of internet connected devices, I currently own just a single HomeKit-compatible device; an Elgato eve door & window that lets me ask Siri if my back door is currently open2. Luckily there is the Homebridge project (which I’ve written about previously) that allows me to connect all of those together and use them as if they were native HomeKit devices.

Over the past few months, I’ve been dabbling with HomeKit scenes so that I can control groups of devices all at once like so:

Good Morning

  • Turns on downstairs lights
  • Starts playing my “morning” playlist in kitchen via AirPlay
  • Disables security cameras

Good Night

  • Turns off all lights (including bedside table lamp)
  • Stops any playing music
  • Enables security cameras

This has been working well but I frequently forget to use scenes as many of these things can be controlled in other ways. For example, I might turn off the downstairs lights with my Hue Dimmer Switch and then turn off the bedside table lamp via the Hue today widget which means I forget to activate the security cameras. The eventual solution I’ve come up with is a simple push button (from Flic) stuck under my bedside table that toggles between my Good Morning and Good Night scenes. In this article, I’ll tell you how I did it!

First of all, you are going to need a Flic. I did a lot of research on “smart buttons” and this one was far and away the best3. It’s small, has a changeable battery (that lasts 18 months), looks good, and it has an iOS SDK complete with background Bluetooth LE support so you can wake your app up even if it is inactive. The amount of code necessary to support Flic is ridiculously small; you can take a look at their iOS tutorial to see it in more detail but essentially you will be kicking your user to the Flic app in order to assign a button to the app. Once you’re back, it’s a simple case of activating a singleton and listening for a manager:didReceiveButtonDown request.

With the button tested and working, I set to work on adding HomeKit support to my app. This is relatively straightforward although you do need to create a dedicated provisioning profile in order to add the necessary entitlements to your project. Within a few minutes, I had a toggle in my app that would toggle between my Good Morning and Good Night scenes. That was when disaster struck; the HomeKit APIs do not work when your app is not in the foreground4.

This threw me for a little while until I decided that my app would simply have to connect directly to my mac and interface with the Homebridge software that was basically powering everything5. After a quick search, I found Homebridge-websocket, a plugin that basically adds a custom websocket server as a platform to HomeKit. You can create accessories (like a switch) within the websocket server and then you’ll get callbacks when they are turned on and off.

I planned to make use of this via a HomeKit property known as “triggers”. A trigger is basically a way for HomeKit to monitor a specific device for a specific value (i.e. when a switch is “on”). As soon as it sees that value, it will activate a chosen scene. I set this up by creating two new switches within Homebridge-websocket; ws_morning and ws_evening. I then set up two triggers within HomeKit; WebSocket Morning (which triggers the Good Morning scene when the ws_morning switch turns on) and WebSocket Evening (which triggers the Good Night scene when the ws_evening switch turns on). The only change I needed to make to my scenes was to ensure that both ws_morning and ws_evening are set to “off” when either is activated; this ensures that I can always turn them from “off” to “on” and thus cause the trigger.

The final step was to update my iOS app to talk to the websocket server instead of to Homebridge. I found a simple drop-in framework named Starscream which allowed me to connect to the server and send commands which led me to this code for the entire project:

import UIKit
import Starscream

let ipAddress = ""
let flicAppKey = "Your-Flic-App-Key"
let flicAppSecret = "Your-Flic-App-Secret"

class ViewController: UIViewController, SCLFlicButtonDelegate, SCLFlicManagerDelegate, WebSocketDelegate {

    let socket = WebSocket(url: NSURL(string: "ws://\(ipAddress)/")!)
    override func viewDidLoad() {
        socket.delegate = self
        SCLFlicManager.configureWithDelegate(self, defaultButtonDelegate: self, appID: flicAppKey, appSecret: flicAppSecret, backgroundExecution: true)

    @IBAction func setupFlic(sender: AnyObject) {
    @IBAction func toggle() {

    // MARK: Flic Manager
    func flicManager(manager: SCLFlicManager, didGrabFlicButton button: SCLFlicButton?, withError error: NSError?) {
        if let error = error {
            NSLog("ERROR: \(error)")
    func flicButton(button: SCLFlicButton, didReceiveButtonDown queued: Bool, age: Int) {
    // MARK: Websocket Delegate
    func websocketDidConnect(socket: WebSocket) {
        let defaults = NSUserDefaults.standardUserDefaults()
        let last = defaults.stringForKey("last_status")
        let name = last == "ws_morning" ? "ws_evening" : "ws_morning"
        let params = ["topic": "setValue", "payload": ["name": name, "characteristic": "On", "value": NSNumber(bool: true)]]
        let data = try! NSJSONSerialization.dataWithJSONObject(params, options: .PrettyPrinted)
        if let string = String(data: data, encoding: NSUTF8StringEncoding) {
            defaults.setObject(name, forKey: "last_status")
    func websocketDidDisconnect(socket: WebSocket, error: NSError?) {
    func websocketDidReceiveData(socket: WebSocket, data: NSData) {
    func websocketDidReceiveMessage(socket: WebSocket, text: String) {

Note: this is just a personal project that I built as quickly as possible. By nature, it is a fairly dirty hack. You shouldn’t write professional apps like this.

With this code in place, I can now press my Flic button (stuck to the underside of my bedside table) and it will toggle between my Good Morning and Good Night scenes. This is the full process of what is going on:

  • Press the Flic button
  • Wakes up the iOS app (if terminated or backgrounded) and hits the toggle function
  • App sends a websocket command to the Homebridge-websocket server
  • Server turns on a fake switch
  • HomeKit notices that the fake switch has been turned on so fires trigger to run appropriate scene
  • Scene activates or deactivates various accessories and then switches the fake switch back off ensuring it is ready for next button press

This is a long way away from the process I’d envisioned (press button, wake up app, toggle scene with HomeKit API) but it has been a fun challenge finding a way to get it work. I now have a physical button that controls multiple aspects of my home with a single press - it’s pretty cool!

  1. Ugh what a horrible expression. I renamed it the Internet of Stuff on episode 7 of The Divide↩︎

  2. Phrasing ↩︎

  3. “Why not just build your own with a Raspberry Pi or similar?”. Because I can’t be bothered; the cost of my time to do that is more than the cost of buying an incredibly well put together button that already does exactly what I want. ↩︎

  4. Probably for a very good reason, you likely don’t want an app reading information about or controlling your HomeKit devices when you aren’t literally using the app. It’s a bit of a pain though for a simple app like this. I did manage to find a entitlement but there is no way to generate a provisioning profile that uses it. Maybe Apple will add this in a future version of iOS but I wouldn’t count on it. ↩︎

  5. Technically, as all of my devices have their own APIs I could have just built my app to directly talk to Hue, Canary, iTunes, etc and rebuild my scenes that way. That idea didn’t sit well with me though as it’d be a lot more work and effectively duplicating what I already have. Similarly, I could have just used the native IFTTT support with the Flic to turn on or off some of my devices but that would add more latency and I don’t want to trust my connected home to something that has to be connected online; the beauty of HomeKit is that it works locally. ↩︎

Fetching RSS Feeds for Steam game updates

I’m currently in the process of switching from my Xbox One to a gaming PC1 and have been spending a lot of time curating my Steam collection on my Mac. One thing I’ve noticed recently is that I often see games being updated but then have to go to their individual pages in order to view the release notes of what has changed (and that is if I even notice a game has been updated). What I really want is a single page that shows me all the patch notes in date order and sends me a notification when something updates.

A quick search found SteamNews, a website that aims to turn Steam Community pages into RSS feeds. However, a lot of games are missing and it doesn’t solve the problem of fetching the feeds for my account; I’d still need to go through and add them manually. I also don’t like relying on 3rd party services which I can’t install on my own server.

After a bit of exploring on the Steam pages, I found that most games have an RSS feed of their news page; this, combined with my publicly available profile page listing my owned games, has led me to write a basic PHP script to loop through my games, find the matching RSS feed, and then add it to my Feedbin account:


define('FEEDBIN_USERNAME', 'your username here');
define('FEEDBIN_PASSWORD', 'your password here');
define('STEAM_ID', 'your steam id here i.e. bendodson');

require 'vendor/autoload.php';
use Goutte\Client;

$html = file_get_contents(''.STEAM_ID.'/games/?tab=all');

$match = "rgGames = ";
$start = strpos($html, $match) + strlen($match);
$json = substr(trim(strtok(substr($html, $start), "\n")), 0, -1);
$array = json_decode($json);

$games = explode("\n", file_get_contents('games.txt'));
if ($games[0] == "") {
	$games = [];
foreach ($array as $game) {
	$unsubscribed = $game->appid.'-0';
	$subscribed = $game->appid.'-1';
	$failed = $game->appid.'-x';
	if (!in_array($unsubscribed, $games) && !in_array($subscribed, $games) && !in_array($failed, $games)) {
		$games[] = $unsubscribed;
file_put_contents('games.txt', implode("\n", $games));

$games = explode("\n", file_get_contents('games.txt'));
$index = 0;
foreach ($games as $game) {
	list($id, $subscribed) = explode("-", $game);
	if ($subscribed == '0') {
		subscribeWithSteamIDAtIndex($id, $index);
	$index += 1;

echo 'Done';

function subscribeWithSteamIDAtIndex($id, $index, $url='') {

	$key = $url == '' ? $id : $url;
	$feedURL = $url == '' ? ''.$id.'/rss/' : $url;
	echo 'Subscribing to '.$feedURL.'<br>';
	$post = json_encode(["feed_url" => $feedURL]);

	$ch = curl_init();
	curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json; charset=utf-8']);
	curl_setopt($ch, CURLOPT_URL, '');    	
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_TIMEOUT, 15); 
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
	$output = curl_exec($ch);
	$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

	if ($statusCode == 404 && $url == '') {

		$success = false;

		$client = new Client();
		$crawler = $client->request('GET', ''.$id.'/allnews/');
		$elements = $crawler->filter('#apphub_InitialContent .Announcement_Card:first-child');
		if ($elements->count() > 0) {
			$url = $elements->attr('data-modal-content-url');
			if ($url) {
				$client = new Client();
				$crawler = $client->request('GET', $url);
				$url = $crawler->selectLink('Subscribe to RSS Feed')->attr('href');;
				if ($url) {
					$success = subscribeWithSteamIDAtIndex($id, $index, $url);

		if (!$success) {
			$games = explode("\n", file_get_contents('games.txt'));
			$games[$index] = $id.'-x';
			file_put_contents('games.txt', implode("\n", $games));			
			echo 'Failed<br><br>';

	} else if ($statusCode == 201) {

		$subscription = json_decode($output);
		$post = json_encode(["feed_id" => $subscription->feed_id, "name" => "Steam Games"]);
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json; charset=utf-8']);
		curl_setopt($ch, CURLOPT_URL, '');    	
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_TIMEOUT, 15); 
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $post);


	if ($statusCode == 201 || $statusCode == 302) {
		$games = explode("\n", file_get_contents('games.txt'));
		$games[$index] = $id.'-1';
		file_put_contents('games.txt', implode("\n", $games));
		echo 'Subscribed!<br><br>';
		return true;

	return false;

There is a fair amount going on in this script2 but the basic overview is:

  1. Fetch a list of owned games from the public profile of the entered Steam ID. Most of the Steam pages are built with Javascript but this page fortunately has the entire library as JSON within the page. After a simple bit of extraction, I have a full list of every game owned.

  2. Update a local text file3 – games.txt – with a list of games. I store each game as an ID followed by a hyphen and a flag to denote whether the game is unsubscribed, subscribed, or failed. For example, if I’m subscribed to the Elite: Dangerous game, the text file will contain 359320-1 as the game ID is 359320.

  3. Just to be a pain, Steam doesn’t have a standard format for it’s RSS feeds. Whilst most of them contain the game ID, some of them don’t. The first step is to go with the usual URL and then if that fails we’ll use Goutte to manually scrape the news page and then the first news item in order to grab the correct RSS feed. For example, the game ID of Counter-Strike: Source is 240 so the script will first try but when that fails it’ll crawl through some pages to discover the correct URL is - there seems to be no logic as to which games have a shorthand name and which don’t and there isn’t an easy way to work out what the name would be.

  4. Once I have a valid RSS feed, it is subscribed to via the Feedbin API. As an added bonus, I also tag the subscription “Steam Games” so they show up all together in my RSS reader of choice, Reeder: Steam RSS feeds in Reeder via Feedbin

  5. Sometimes, the process might fail as in the case of Titan Quest which has no updates and thus no RSS feed. If that happens, the game is marked in the text file so that it can be safely ignored. In my own version of the script, I added Slack integration so I get a notification when a game fails so I check to see if it is a simple case of no feed or if my script has broken: Steam RSS feed failure in Slack

I have the script set up on a cron so if I purchase a new game the RSS feed for it should appear in Feedbin within the hour4.

One idea I dabbled with was fetching the feeds myself and building a single large RSS feed that I could subscribe to. There are a few issues there though:

  • It would require me to constantly fetch each feed which could be huge if I own hundreds of games. I already pay for my RSS subscription service (Feedbin) so why add more complexity when they can do that for me?

  • I’d be sacrificing some customisation. If I’m not interested in a specific game, I can simply remove the feed from Feedbin. My script doesn’t check subscriptions so it won’t try and re-add it.

  • There is no benefit to one large RSS feed. If I was doing this as a commercial service (i.e. a hosted page where you enter your username and I give you a single feed) then it may make sense but I’m not interested in doing that5.

I’ve put all of the code on GitHub in case it is of interest to anyone.

  1. The main reasons being far higher resolution and quality, cheaper games, and virtual reality. I’ll miss Xbox achievements but the boost in visual quality more than makes up for that (and with controller support and a SteamLink, I can still play most games on my sofa with an Xbox One Elite Controller). ↩︎

  2. Please do not look at this and assume this is any way good practice. This is a very fast and loose piece of coding in order to achieve a specific goal as quickly as possible; most of it will break if Steam update their HTML pages (very likely). ↩︎

  3. “Why not use a database” - I couldn’t be bothered to set one up. A basic text file does the job. ↩︎

  4. “Within the hour” - can you tell I’ve been rewatching 24 lately? ↩︎

  5. When I was younger, that is exactly what I would have done but as I’ve grown older I’ve realised that hosting stuff for free is a massive headache. Much better to stick the code on GitHub and let people use it on their own if they want. ↩︎

AirPlay Alarm Clock with iTunes 12

A few years ago, I wrote a convoluted AppleScript that allowed me to use my Apple TV as an alarm clock. It worked by waking up iTunes, selecting a playlist, shuffling it, and then playing it via AirPlay. Unfortunately, it stopped working when iTunes 11 was released due to a number of changes to AppleScript support; there were also changes to OS X which prevented AppleScripts from launching via Calendar alerts.

Fast forward to today and I found myself needing this script again for a new project1. After a bit of hacking around, I’ve managed to get the script fully updated for iTunes 12:

set AirplayDeviceName to "Kitchen"
set PlaylistName to "Morning"
set AirplayVolume to 100

activate application "iTunes"

tell application "System Events"
	tell application "iTunes"
		set visible of front browser window to true
		set the view of the front browser window to playlist PlaylistName
	end tell
end tell

tell application "System Events"
	tell process "iTunes" to if exists then
		click menu item "Songs" of menu "Shuffle" of menu item "Shuffle" of menu "Controls" of menu bar 1
		click menu item "On" of menu "Shuffle" of menu item "Shuffle" of menu "Controls" of menu bar 1
	end if
end tell

tell application "iTunes"
	set AirplayNames to (get name of AirPlay devices)
	set AirplayDevices to (get AirPlay devices)
	set AirplayToPlay to {}
	repeat with i from 1 to length of AirplayNames
		if item i of AirplayNames as string = AirplayDeviceName then set end of AirplayToPlay to item i of AirplayDevices
	end repeat
	set current AirPlay devices to AirplayToPlay
end tell

tell application "iTunes"
	play playlist PlaylistName
	set the sound volume to AirplayVolume
end tell

The script is significantly smaller thanks to some new AirPlay APIs within iTunes and I’ve updated it to allow for simple changing of volume. It should work in all versions of iTunes 11 and iTunes 12.

In order to get this working as an alarm, we have to jump through a number of hoops on OS X El Capitan. Firstly, we need to save our AppleScript as an application (after you’ve made any adjustments to your Airplay device name, playlist name, and the volume you want). You can do this by opening it within Script Editor and then choosing File > Export.

Export AppleScript as Application

If you haven’t disabled the GateKeeper restrictions on your Mac, you will need to either Code Sign this app or grant an exception within the Security & Privacy settings after you have first tried to open it.

With the alarm exported, we now need to open up Automator and create a new Calendar Alarm. Find the Launch Application action and set that up to point to your newly exported alarm app. Finally, save this and you’ll find a new entry has appeared in your calendar; it will launch immediately thus starting off the iTunes alarm process. Simply copy and paste this alarm entry (or make it recurring) in order to set it to whatever times you want.

I’m going to continue playing around with different ways to launch the alarm but for now this works in much the same way as my old script did.

The full code (and previous version) is available on GitHub.

  1. I’m experimenting with some HomeKit APIs with the aim being that my “Good morning” scene can be activated by a physical button and will not only turn on my lights and disable my security camera but also start playing my morning playlist in the kitchen. This is what I do for fun. ↩︎

The Divide #12 - Reboots

The 12th episode of The Divide podcast is now available in which we have a lengthy discussion on reboots, particularly in movie franchises like Spiderman, Batman, and that film by that director we’re not allowed to mention in front of Chris. In addition, we address some board game follow-up, tell you how to test a HTC Vive in the UK, and get all excited at the prospect of a new Red Dead Redemption game!

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.

Emoji flags from ISO 3166-1 country codes (in Swift)

I’m working on a personal project currently that works heavily with country codes and the selection of countries. To make it look better, I wanted to use a flag icon for each country in the list. In the past, this would have been done with a load of imported images named something like “gb.png” but luckily there is a modern solution; emoji!

As of iOS 9.0, every ISO 3166-1 country now has a corresponding emoji flag1. The way to build them is also incredibly simple as you basically put the two letters together as joined Unicode characters. Benjamin Esham explains it like this:

What they did is both crazy and genius. Instead of assigning a codepoint to each flag, which is the obvious way to do it (and the way the rest of the emoji are encoded), the standard defines twenty-six “regional indicator symbols”, from U+1F1E6 REGIONAL INDICATOR SYMBOL LETTER A to U+1F1FF REGIONAL INDICATOR SYMBOL LETTER Z. In order to include a country’s flag in your text, you first look up the country’s two-letter ISO 3166-1 code and then write the two regional indicator symbols corresponding to those letters. A font with support for that flag treats the two-codepoint sequence as a ligature, replacing the combination with a single pictogram.

Let’s take the United States as an example. Its ISO 3166-1 two-letter code is “us”, so we need to use the codepoints U+1F1FA REGIONAL INDICATOR SYMBOL LETTER U and U+1F1F8 REGIONAL INDICATOR SYMBOL LETTER S. Combining these gives a symbol that renders in your browser as 🇺🇸.

Armed with this information, it is easy to write a basic function to turn a code like “us” into the corresponding flag emoji:

func emojiFlag(countryCode countryCode: String) -> String {
    var string = ""
    var country = countryCode.uppercaseString
    for uS in country.unicodeScalars {
        string.append(UnicodeScalar(127397 + uS.value))
    return string

A great way of testing this is with an Xcode Playground which will allow you to quickly see the output like such:

If you use an incorrect code such as “en”2 then you’ll be given back the letters within boxes.

You can download my example playground from GitHub.

  1. Most were supported in iOS 8.3 but hidden from the emoji keyboard; iOS 9.0 added an extra 40 to complete the set including such places as Antarctica and Taiwan. They also added support for the EU flag. ↩︎

  2. England is not an iOS 3166-1 country and so there is no “en” code. There is a proposal for subdivisions to be supported so something like “gb-eng” would work but it is not accepted yet and iOS has no flags for places like England, Wales, or Scotland. ↩︎

iPhone 7 headphone predictions

I don’t tend to make many Apple predictions but I’ve been meaning to write about the rumour of the lack of a headphone port on the iPhone 7 for some time. It seems almost certain that the iPhone 7 will drop the 3.5mm headphone jack in favour of using the proprietary lightning port and this has caused a lot of consternation in the tech press. This is understandable as there are several issues with doing this:

  1. You wouldn’t be able to use headphones you already own (potentially very expensive headphones).

  2. If you were using lightning headphones, you wouldn’t be able to charge your phone at the same time.

  3. Whilst Bluetooth is an option, it can have lag (only annoying on video) and you have to remember to charge them.

The solution to the first problem is very simple; there will be an adapter accessory1 to allow you to plug 3.5mm headphones into the lightning port. I personally don’t have a problem with this; if you have expensive headphones and an expensive phone, the cost of buying an adapter is negligible really and it is unlikely to add any bulk as it’ll just be extending the cord that you’ll already be using. You are unlikely to buy an adapter to use the existing bundled EarPods as it is certain that Apple would bundle in some lightning powered EarPods so really the adapter is for those with existing expensive 3.5mm based headphones.

However, the other two issues are more problematic. There is an issue that you may very well want to charge your iPhone whilst listening to music via headphones and Bluetooth does suck when you are watching video as it is often out of sync by a few milliseconds. I own a pair of Beats Studio Wireless which connect either via Bluetooth or via a 3.5mm cable; I regularly use the cable when watching Netflix in bed as I find the lag incredibly irritating2. In addition, I can charge my phone at the same time.

Some people have proposed that the iPhone 7 could get conductive charging much like the Apple Watch but this seems highly unlikely to me; the amount of space required to do that is huge (compared to a 3.5mm jack) and it charges very slowly, especially with an iPhone 6 Plus sized battery.

I have two predictions which I believe solve these issues:

  1. The bundled headphones will be lightning but will have some sort of lightning passthrough so you can continue to power your device or use any other lightning accessory at the same time.

  2. There will be wireless headphones that will work with some new proprietary sync method3 but can also work with a lightning cable for both listening and charging. They would be called “AirPods” and would either be bundled as the lightning headphones or be available separately for something like £79 / $99. A recent patent that was unearthed would seem to indicate this as a solid option. Extra points to Apple if it is a custom wireless solution and it works with the Apple Watch 2.

Both of these proposals get around the charging issue and the Bluetooth lag issue. I think it more likely that we’ll get basic lightning headphones included and then have to pay for the fancier lightning / wireless ones but it isn’t outside the realm of possibility that they could be bundled. That said, I also wouldn’t put it past Apple to say “you can use headphones or you can charge your phone” similar to the “charge or use peripheral” attitude to the solo USB-C port on the MacBook4.

The only thing that seems certain is that the 3.5mm port will not be available; you’ll need to use either an adapter or whatever new headphones Apple release.

  1. Likely priced at $29.99 / £24.99 because they can. You’ll get a cheap version on Amazon for $9.99 / £6.99 within a month. ↩︎

  2. I couldn’t care less about audio lag for listening to music or podcasts as it really doesn’t matter and isn’t noticeable; it only affects video as 50ms of lag will mean that the actors lips don’t move precisely with their voice which is offputting. ↩︎

  3. They would probably use the “AirPlay” brand. ↩︎

  4. Which I own and have had no issues with. Interesting that it retains a 3.5mm jack though when a USB-C port on both sides would make more sense to my mind. ↩︎


An iPhone app I worked on throughout 2015 has finally gone live in the App Store today; Clinix:

I worked with Clinix throughout 2015 as the exclusive iOS developer on their medical app. Clinix is a doctor-patient video consultation platform targeted primarily at the NHS. It provides patients with an Electronic Medical Records system that syncs automatically with their GP records. You can view and update allergies, medical history, and medications as well as make video appointments with your GP.

The app was built using Swift and interfaces with the OpenTok video APIs. I helped with the initial design of the PHP-based API and was integral in making UX decisions throughout the app.

Clinix is a free app and is available on the App Store.

Connecting To Host

I’m very happy to announce that a new podcast I’ve been working on with John Wordsworth has gone live today; Connecting To Host.

Connecting To Host is a (mostly) weekly podcast where we discuss video games from a strictly co-op / multiplayer point of view. We’ve released three episodes today:

  • FORCED: Specifically built for co-operative action, FORCED is an arcade RPG which takes you through a number of challenging arenas. Join us and find out more about “The Orb” and “Marking up Enemies”, two strong mechanics that make FORCED a fun little online game.

  • Torchlight II: Join us as we talk about our co-operative experience working through Torchlight II, an action RPG developed by Runic Games that was originally released at the end of 2012.

  • Titanfall: With the recent announcement of Titanfall 2 for Xbox One, PC, and PS4, we thought we would go back in time and talk about the original Titanfall and what it brought to the multiplayer shooter genre.

I’m really excited about this podcast and think it’ll be a great way for people to get co-op specific reviews from two long time game players who spend several hours a week playing online together.

You can get Connecting To Host from these fine outlets:

If you enjoy the podcast, please consider leaving a review on iTunes or letting us know on Twitter via @CTHCast; you can also suggest games you’d like us to review!

Our next episode will be on Saturday 23rd April 2016 and is all about Offworld Trading Company

Thoughts on ringtones

Today I spent a little bit of time making a new iPhone message tone1 and it reminded me of how terrible the entire ringtone system is on iOS. I have a number of specific issues:

Overpriced - most ringtones cost the same as a full song despite the fact they are shorter than the free preview on iTunes or they are a couple seconds of audio from a TV show or film. The pricing hasn’t changed since the ringtone store was launched in iOS 3 but the quality has definitely deteriorated with a number of dubious looking alert tones ripped from TV shows or YouTube videos.

DRM - as well as being shorter than a full song for the same price, they are subject to DRM whereas music is not. They’re also in a proprietary format so you can’t re-use them on non-Apple devices.

iTunes - you can create your own ringtones using GarageBand2 but the only way to get them onto your iPhone or iPad is to do a sync with iTunes. Eugh! We were supposed to have moved away from this when iOS 6 cut the iTunes cord but I couldn’t find any other way to get the *.m4r file over to iOS (I tried messaging it to myself and using Dropbox but neither option allowed you to then save it to your settings).

iCloud - for some bizarre reason, ringtones are not synced via iCloud in the UK so if you haven’t backed them up you’ll lose them when setting up a new device. There is no option to redownload them from iTunes and if you purchase one you’ve previously downloaded you will be charged (you don’t even get a “you’ve previously purchased this” dialogue like you do with music, tv shows, and movies). I’ve purchased a few tones in the past3 but none of them are available to me unless I pay again.

I don’t have a solution to this (apart from killing the ringtone store and allowing you to just use MP3 files) but it is an area of the iOS ecosystem that is definitely showing it’s age. At the moment, you either have the expense and DRM protected (with no redownloads) way of purchasing or you can jump through hoops making your own and trying to get them onto your device. I’m not sure how either is seen as acceptable.

  1. It’s Han Solo shouting ‘BEN!!’ from Star Wars: The Force Awakens ↩︎

  2. I’m specifically referring to GarageBand on the mac although I believe it is also possible with GarageBand for iOS. ↩︎

  3. I used to have the T-Rex Roar from Jurassic Park as the alert for my wife but she didn’t care for it; I now have Lando Calrissian saying “Hello, what have we here?” ↩︎

« Older Entries Newer Entries »