URL encoding an NSString on iOS

I’ve been working on an iPhone app for the last few weeks, which I’ve really enjoyed. Every now and again, though, you hit what seems like a bug in the iOS SDK.

This seems to happen much more frequently than it ever did when I was coding in C#. As a result, my default debugging approach – that any problem with my app must be my fault rather than something in the framework – has shifted slightly. I’m now much more likely to question the framework itself, and with a quick Google search it’s common to find other developers who have experienced the same problem.

Here’s one that bit me recently. NSString has a method calledstringByAddingPercentEscapesUsingEncoding, which purports to make the string safe for use, say, as a parameter to a URL. There are several characters that are reserved in parameters toURLs – for example the slash character, or the ampersand, because these are characters that are used to delimit the URL itself. Therefore we encode these, and this is done using the percent encoding scheme.

As an example, if you want to use the string hell & brimstone + earthly/delight (and why wouldn’t you?) as a parameter to a URL then you’ll need to convert it to ﻿hell+%26+brimstone+%2B+earthly%2Fdelight so that the ampersand becomes %26, the plus becomes %2B and the slash becomes %2F. Note that spaces are encoded as pluses, which is why the original plus sign needs to be encoded.

It fails to encode the ampersand, the slash and the plus, and many (most?) web servers will be confused by that. It encodes the spaces as %20, which is just as acceptable as encoding them as a plus.

In short, it’s completely broken, which is frustrating. But thankfully there’s a lower-level API we can use which, thanks to the magic of Objective-C categories, we can tack on to NSString. This is based on a blogpost by Simon Woodside, which I’ve just turned into a category.