Creating a URL query string using an NSDictionary

I finally got round to making this into a category. It's a simple function for turning a dictionary into a query string, ready for appending to the end of a URL.

[sourcecode language="objc"]
// NSDictionary+QueryStringBuilder.h

#import <Foundation/Foundation.h>

@interface NSDictionary (QueryStringBuilder)

- (NSString *)queryString;

@end
[/sourcecode]

[sourcecode language="objc"]
// NSDictionary+QueryStringBuilder.m

NSString * escapeString(NSString *string)
{
NSString *s = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)unencodedString,
NULL,
(CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
kCFStringEncodingUTF8);
return [s autorelease];
}

@implementation NSDictionary (QueryStringBuilder)

- (NSString *)queryString
{
NSMutableString *queryString = nil;
NSArray *keys = [self allKeys];

if ([keys count] > 0) {
for (id key in keys) {
id value = [self objectForKey:key];
if (nil == queryString) {
queryString = [[[NSMutableString alloc] init] autorelease];
[queryString appendFormat:@"?"];
} else {
[queryString appendFormat:@"&"];
}

if (nil != key && nil != value) {
[queryString appendFormat:@"%@=%@", escapeString(key), escapeString(value)];
} else if (nil != key) {
[queryString appendFormat:@"%@", escapeString(key)];
}
}

return queryString;
}

@end
[/sourcecode]

Using this category is very simple;

[sourcecode language="objc"]
NSDictionary *queryParameters = [NSDictionary dictionaryWithValuesAndKeys:1, @"page", nil, @"enabled", 25, @"size", nil];
[queryParameters queryString]; // This will return "?page=1&enabled&size=25"
[/sourcecode]

You can get the sourcecode as a gist.

Written on May 14, 2011