Our products

We are passionate about building niche multi-platform products that provide real utility to our customers.

Keep up to date with Liverpool FC news from across the web.
Domain Bites
Domain name industry news and resources.
Pub Reviews
Find the best pubs near you. Share your thoughts and photos.
Capture your taste and share it with the world.


We like to blog about software. Our stack, engineering problems, open source developments.. you will find it all discussed here.

iOS push notifications - the succinct explanation

iOS push notifications are (in my personal opinion) suprisingly difficult to implement properly and debug.

This is especially suprising given that Apple have provided such in depth documentation, and given that there are such an abundance of tutorials on the topic.

The problem is that no single resource has a succinct yet complete explanation. Here it is.

The user needs to be registered for APNS to receive notifications

  • A user can not, and will not ever receive APNS notifications from your app unless they have given explicit permission.

  • In Swift, this can be done with the following code snippet:

let types = UIUserNotificationSettings(forTypes: [UIUserNotificationType.Alert, UIUserNotificationType.Badge, UIUserNotificationType.Sound], categories: nil)  
  • Many suggest placing this in your app delegate to request permission on the initial application load. I disagree - you should request permission in response to any explicit user action e.g in response to clicking 'Set up notifications' on your 'Settings' page.

If you want to download data in response to receiving a notification

  • you must add the following property to your plist
  • You can make your notifications silent by specifying an empty 'sound' key in your payload. Likewise you can display no notification message by setting the 'message' key to an empty value.

Handling all application states

  • If your app is open, and in the foreground you will receive one call to application:didReceiveRemoteNotification:fetchCompletionHandler:.

  • You can check the applicationState property of the passed in application argument. In this case the state will be UIApplicationState.Active

  • To respond to receipt of a call to this delegate method I find it best to dispatch a NSNotification from the default notification center instance. Having already set up an observer in the appropriate view controller, you can pass control over to said controller easily on receipt of the notification.

  • If your app is in the background, you will receive two calls to application:didReceiveRemoteNotification:fetchCompletionHandler:. The first one when the notification is received. The second when the notification is clicked.

  • The first time your application state will be UIApplicationState.Background. The second time it will be UIApplicationState.Inactive

  • Because the application is open (it is just in the background), on receipt of the first call I (again) dispatch a NSNotification that the appropriate controller is listening for. On the second call (when you are bringing the app to the foreground), I do nothing - there is no need to dispatch a second notification.

  • *If your app is closed, you will only receive one call to application:didReceiveRemoteNotification:fetchCompletionHandler: - when the notification is clicked.

  • When closed, there is the additional consideration that your view controller has not been instantiated fully at the point that the application:didReceiveRemoteNotification:fetchCompletionHandler: delegate method is called. As such there is no point dispatching a NSNotification as the observer to listen for it is not set up.

  • In this case, I access and manipulated my view controller directly. You can cast the visibleViewController as you (should) know what your initial view controller is.

let postsController = rootNavController?.visibleViewController as! PostsController  
  • You can then set properties directly on the view controller instance which you can then check for (and act upon) in the viewDidLoad method of the controller.

Tips and tricks

  • If you pass a 'badge' value in the array set as the value for the 'aps' key of your payload, then the system will set the badge on your application icon even if your application is closed.

  • When your application is open or in the background, you can access the current badge value using:

let currentBadgeNumber = UIApplication.sharedApplication().applicationIconBadgeNumber  
  • You can use this knowledge to increment/decrement the badge count within your didReceiveRemoteNotification based on downloaded data. You cannot increment/decrement when the application is closed.

  • When you open the (previously closed) app by clicking on a notification, you can see if the app is being opened due to such a click in the didFinishLaunchingWithOptions method of your AppDelegate with the following code:

let notificationInfo = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey]

if (notificationInfo != nil) {

    //do something
  • APNS IDs change ! Even the same version of an application on the same device can have a new APNS ID should you uninstall and then reinstall it. Always check, and keep your server in sync. You might not be receiving notifications because you are sending them to a registration ID that is no longer valid

Register the registered every time

  • That final tip is important enough to warrant its own section. I like to register any previously registered user for APNS in my didFinishLaunchingWithOptions AppDelegate method every time

  • registerForRemoteNotifications is clever. As noted in the documentation:

If your app has previously registered, calling registerForRemoteNotifications results in the operating system passing the device token to the delegate immediately without incurring additional overhead.  
  • That is to say, you may as well check every time the application is loaded if the registration ID has changed. When you sync you registration ID with the server you should also save it locally (perhaps in NSUserDefaults or in your keychain - see SSKeychain). Then in the didRegisterForRemoteNotificationsWithDeviceToken delegate method you can check whether the registration ID has changed.. and if it has, resync it with the server.

The server

  • I am not going to reinvent the wheel. The PHP server code outlined in this tutorial from Ray Wenderlich is good.

  • One thing to note. I found that sometimes, without reason I would get disconnected from the APNS server. I recommend that you dont hide the error output of the following line:

$result = fwrite($this->fp, $msg, strlen($msg));
  • That way you can debug any issues that occur. I didn't find any particular reason for my occasional disconnects, so I simply implemented the appropriate code to establish a new connection should a disconnection occur.

Testing APNS

  • You obviously want to test that your notification setup works correctly prior to releasing your application.

  • Given that APNS profiles are associated with your application bundle identifier I have found that is significantly easier to have distinct bundle identifiers for your development and production applications. This has the added benefit that you can have a development version, and production version of your app on your device side by side. Likewise you can utilise different app icons for each. I recommend that you follow this guide from the team at Circle to get things set up.

  • You can utilise a single bundle identifier (if you wish), but to provision an application for testing (in a manner that will work with the APNS sandbox server) you have to export the application for 'Ad Hoc' deployment from your 'Organizer' and manually put it on your device (through iTunes).

  • Assuming you have gone for the former (better) option, you can simply setup a local server instance to send notifications to the APNS sandbox. Easy.

  • If you are not receiving notifications, my first recommendation as regards debugging is to always make sure you are connecting to the correct APNS server (sandbox vs production), and to make sure that you are using the correct APNS registration ID. Debug and production keys are different.


Having spent a long time looking into the intricacies of APNS it now seems incredibly simple. That said, there are a number of moving parts, and the smallest oversight can cause your notification system to not work at all.

Hopefully the above provides a succinct explanation of those intricacies such that you can implement APNS within your applications without issue.

Let me know how you get on, and if you have any questions/require further clarification.. let me know.

LeedsTechHub - Much Sky, very pizza

These are my (personal) thoughts on 'Building Mobile Apps For A Global Audience In An Agile Way' - a meetup organized by Sky as part of their LeedsTechHub concept.

I found the event to be generally fantastic. Being based in Leeds it is certainly great to see tech investment coming into the city. There were four talks, each of which I have briefly outlined below.

Silent Running - Dark Launches, Feature Toggles & Avoiding Technical Debt – Tim Antrobus - Mobile Developer at Sky

A polished presentation that got me thinking. Given Apple's drawn out review process, I was intrigued as to what Tim might have to say on ways of ensuring that bugs don't creep through the net.

Unfortunately this was very much a 'these are things to consider' as a resolution for 'this list of problems' kind of presentation. It was (I assume) intended to be a very basic catch-all (levels of engineer) introduction to issues with continuous deployment.

I would have liked to have seen more hands on examples of usecases within products.

Tim did mention that he had played around with writing Pachinko, a wrapper of sorts around feature toggles for utilisation in iOS apps (using Swift). This looks very interesting - I am going to have a play with some ideas that I have had in relation to this as/when I get a chance.

Feature toggles, and dark launches are interesting concepts and I am glad that Tim bought them to the forefront of my attention. Unfortunately within the small team here at Double Negative, there are very few patently obvious practical benefits.

I had naively hoped that Tim might be able to provide a resolution to the situation whereby you notice that an in production iOS app has a visually disastrous constraint issue on the smaller screen of the 4s (this happened). Unfortunately he did not.

Mobile Agility – Thinking Beyond the App – Nikunj Patel - Head of Mobile Assurance at BJSS Ltd

Nikunj scoffs at the idea of releasing an enterprise app to the app store through a developer computer. I found this rather amusing. If anything, the constraining nature of Apple's review process means that this is 'kind-of' OK in my opinion. After all, you have ten days to notice any issues and resolve them. That said, I do appreciate his point.. as a general rule it is perhaps not sensible to release in such a manner.

Again, this presentation was what I would describe as an overview (understandable given the short time constraints). It did however draw attention to some home truths that I had not really considered previously. For example the idea that nowadays "Slowness and unresponsiveness is no longer acceptable" - it is weird to think that not too long ago slowness was OK. Not only was it OK, it was the norm !

There were some very interesting tidbits of information contained within. For example the fact that by 2020 Cisco projects that there will be seven times more networked devices than people !

His "Solution level approach to delivery" was interesting. Conceive, Design, Develop, Deploy.. with significant energy being allocated to the Conceive and Design stages.

Personally I feel as though I follow this approach with my development projects but I have never formalised the process - I can absolutely see merit in formalising this approach to prevent issues down the line.

Continuous Integration in the Cloud for Mobile Applications - Jagdeep Nagpal - Engineer in The Sky Store Android Team

As a developer it is a little strange the extent to which the word 'Gradle' stresses me out. Stating the word Gradle, and then showing me a Gradle configuration file is definitely not the way to make me smile.

The long and the short of this talk was that continuous integration and deployment can, and should be done in the cloud. Sky does (using CircleCI).

This presentation seemed a little outdated in that I cannot imagine any engineer in the room would be considering setting up their own Jenkins rig. Even if they were.. surely any agile engineer would be smacked around the head with a keyboard by another member of their team should they genuinely and sincerely make such a proposal..?

The need for a modular approach when delivering global cross-platform apps. - Tom Cooke - Scrum Master for Sky Sports Mobile Apps Team

This presentation again highlighted some interesting points, and showcased problems and progress in mobile app development.

The long and the short (the title gives it away) was that modular design is good. Consideration of the future and the ability for reuse is important. Time is money, so get it right first time.

I was completely bemused that in reference to cross platform frameworks, React Native was not mentioned. I don't personally use it but I do love Facebook's open source efforts. I feel that React Native has a lot more potential than some of the awful frameworks that he did mention.

It was especially strange given the in depth analysis of Facebook's engineering strategies in regards to mobile over the years discussed earlier in the presentation.

That said I am very much a fan of native app development.. as in development for each platform. As such it is somewhat irrelevant (to me) :)

This presentation posed some initial questions, which it then went on to answer. I liked this approach - it works well in relation to software discussions. The number of times that Tom said the word 'modular' indicates to me that he is very passionate about modular design :)

Some general thoughts.

Of course, given the nature of the event there were time constraints, but I found that the talks focussed on the general and ignored the exciting, new, and tough (yet relevant) subject matters.

My notes at the end amounted to a list of buzz words - concepts, and product names which had been mentioned but not discussed. I then proceeded to investgate them myself..

I had never heard of Zeplin (meh) or JustInMind (looks interesting - I am pretty sure Nikunj must be on their payroll ;) ). Nor had I heard of Realm (this looks especially awesome).

There was mention of the need for testing yet nothing on the 'how-to' side of testing mobile apps (something which I have personally found notoriously tough).

Likewise whilst saying modular code is good but hard is.. true, it does not help me develop more modular code.

So.. overall, a very interesting set of presentations, just not what I had expected. They certainly got me thinking, and hopefully my observaions can serve as ideas for future events.

I would love to see an event with one talk focussing on one tough problem - "How to unit test effectively on iOS", "How to continuously build an Android app (hands on)" etc

The end

For me it was a great first event. The few small shortcomings were very much made up for by the abundance of free pizza provided afterwards (although my diet would certainly disagree).

If you are considering attending the LeedsTechHub in the future.. I would.

Character encoding 101

As a software engineer, it is to all extents and purposes a requirement that one has at least a basic understanding of (and appreciation for) character encoding. On that basis, before we go any further I must implore you to read Joel Spolsky's article on Unicode.

I have recently been working on two projects that have encountered various issues associated with character encoding. I was naively oblivious to exactly what I needed to do in each case (as regard character encoding) so went about learning more (and writing about it here).


Recently I have been developing an iOS/web app combination for Mmmm - a social food photography application.

It was extremely important that the website and application were able to display characters from every different alphabet.

The intention is that the application will be utilized across the globe, and photographs will be submitted of local foods. As such, one can safely assume that the captions, tags, and location names associated with various photos may well utilise different character sets.

The application interacts with our backend through our API.

Our requirements are thus:

  • Characters from any alphabet are displayed correctly on the web
  • Characters from any language can be transmitted across the wire

As outlined in Joel's article, the requirements for displaying a particular character set on the web is that you set the appropriate meta tag:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

For our API responses we simply specify the content type as application/json instead.

Within our iOS application we utilise the Alamofire networking library. As can be seen in this pull request, the library is built to respect the content encoding returned by the server. That is to say that specifying our charset as UTF-8 in our response allows Alamofire to appropriately handle the response and return it in the correct format to your callback.

Interestingly, as per the JSON specification, "JSON text SHALL be encoded in Unicode. The default encoding is UTF-8."

Domain Bites

Another project on which I have been working is Domain Bites - an application for keeping up to date with news pertaining to the domain name industry.

Whilst the majority of articles displayed through the app are written in English (using English character sets), it is not safe to assume that that will always be the case.

In addition to this, the content being displayed is being pulled from the RSS feeds of various industry blogs. Given this, we cannot guarantee how article data will be transmitted through the feed.

One issue that I encountered with this project was that a number of feeds were returning data containing HTML entity codes. For example &#8217; would be returned instead of an apostrophe. This obviously affects readability.

As outlined here, these codes are hexadecimal representations of unicode code points (see Joel's article). In some cases entity names were also being returned such as &nbsp; (These names are often used as they have the benefit of being somewhat more memorable).

** If you are interested, these codes are often utilised to make things explicit. For example utilisng the &nbsp; entity makes it patently obvious that a space should be displayed. Some characters (for example < and > need to be outputted in their entity format (&lt; AND &gt;) because < and > have special meanings within HTML. You can view a full list of character entity references in the HTML5 specification here.

As these character references reference a particular unicode code point, they are easily convertable to their unicode counterpart. PHP for example provides the html_entity_decode method which does this for you.

Given that I store the pulled articles in my database I thought it interesting to also note that one can store raw data within most modern databases. With this particular project, I decode the received data utilising html_entity_decode prior to saving it in my (mySQL) database. The table in question utilises the UTF-8 character encoding and as such there is no reason not to store UTF-8 characters in their raw format. You'll save a negligible amount of space too !

As answered here, you can verify the encoding of your (mySQL) database using the following:

SHOW TABLE STATUS where name like 'table_123';

Interesting other stuff..

Whilst writing this it crossed my mind that 'UTF-8' seems to be ideal for.. everything. Why would anyone utilise a different character set?

Well.. it definitely wasn't a stupid thought - it seems there is even a manifesto outlining exactly why UTF-8 should be utilised everywhere, and why it should be the default encoding type.

There are however a few disadvantages outlined on Wikipedia - I am however not convinced.


As you can see, character encoding issues are not exactly tough to resolve. You do however need to be aware of them, especially if you rely on data from external sources - data, the format of which you can not guarantee.

Had I not considered character encoding I would have limited the potential market for Mmmm to a paltry 850 million people source, and would have risked slightly annoying people trying to keep up to date with domain name news.

Given that it is so simple, you should definitiely give consideration to it. Its kind of interesting too :)

Transpilers, parsers, and shims

My current build process for PubReviews.com utilizes Grunt.

On occasion I have seen 'Esprima' outputted within my build logs.

I have always been happy to allow the internals of the tools which I utilize for build and release cycles to keep their internals relatively hidden.

That was until today..

Having spent a large majority of my time working on other projects, I have not been keeping up to date with open source developments.

The Pub Reviews project utilizes React for its client side, but was back in the stone age utilizing 0.11. As such I decided that I would get myself up to date with recent developments, gain a more thorough understanding of some of tools I am using (behind the scenes), and document it here.


As defined by Wikipedia:

"A source-to-source compiler, transcompiler or transpiler is a type of compiler that takes the source code of a program written in one programming language as its input and produces the equivalent source code in another programming language."


Historically one could write their code in JSX and then convert it into pure javascript utilizing a transpiler (as part of a build process) or an on the fly conversion process.

Utilizing the JSTransform tool that was packaged as part of react-tools, one could utilize a command such as sudo jsx --watch jsx/ js/ --extension jsx to watch all changes to JSX files in a given directory, and convert them on the fly.

Such a setup allows quick development iterations without have to compile JSX inline/on the fly.

As of 0.14, this has been deprecated along with react-tools (see here).


Babel is the transpiler that is currently recommended for use by the React team (as of 0.14).

It converts JSX into Javascript as well as a number of other transformations to make sure that the code you write works in all currently available environments. For example it converts ECMA6 syntax into syntax that will work in the current browser iterations.

It also provides a browser version which completely replaces JSXTransformer for those of you were converting JSX inline on page load.



Esprima is a parser which takes your Javascript code and parses it into a semantic explanation formatted as JSON (an Abstract Source Tree (AST))

It is useful for parsing code for utilisation within IDEs (autocompletion) as well as for transpiling code - it is the parser utilised in JSTransform.

It allows for code that is never used to be discovered (and removed) alongside various forms of syntax validation. It can then be converted back to Javascript code utilising escodegen.

Whereas a linter (for example jslint might check that certain stylistic standards are followed, the Esprima pass validator simply makes sure that the Javascript engine will understand it. It does not have to be good code. Esprima even provides an online code validator which you can have a play with.

One of many

Whilst Esprima is the parser that has been popping up in my console, there are in fact many alternatives. For example acornjs, AND UglifyJS 2.

AST Formats

Both Esprima and acornjs utilize the Spider Monkey AST. It is a well documented format, developed in house over many years by Mozilla. UglifyJS2 utilises its own AST for reasons outlined here.


Whilst the title 'Shims'is pretty generalised, they are an important part of my build process.

The definition of a 'Shim' as told by Google is:

"a washer or thin strip of material used to align parts, make them fit, or reduce wear".

In software, it is exactly the same - it is a tool (piece of code) that allows for code utilising one API to interact with code utilising another API. It is the adapter aspect of the adapter design pattern.

Within my codebase I utilise browserify-shim, and my own set of shims for working with PhantomJS.

browserify-shim is designed to "Make CommonJS-Incompatible Files Browserifyable". It allows me to make libraries (jQuery, bootstrap etc) that are loaded from CDNs (and are thus in the global scope) accessible to browserify such that I can build my javascript for utilisation in the browser using simple require calls.

Interestingly, browserify also works by building an AST and parsing it to build up a graph of dependencies !

Because I utilise PhantomJS for the functional testing of a number of my projects, I want the browser environment in which I test to be as close to the browsers than people ctually utilise to access my products. PhantomJS 1.9.2 did not support Function.prototype.bind natively (here is why), so I was required to utilise a shim (polyfill) implementation of the bind method to make calls to the method work within my test environment.

Obviously, adding code purely for testing is not ideal - this was always a temporary solution. Fortunately as of PhantomJS 2 this is no longer a problem and as such the shim has been removed.


So there we have it. A brief overview of some interesting tools/concepts that may be of use to you whilst building your projects. If there are any topics that you'd like to read about, please let me know and I'll do my best to blog about them!