views:

173

answers:

2

I created a method to build URLs for me.

- (NSString *)urlFor:(NSString *)path arguments:(NSDictionary *)args
{
    NSString *format = @"http://api.example.com/%@?version=2.0.1";
    NSMutableString *url = [NSMutableString stringWithFormat:format, path];

    if ([args isKindOfClass:[NSDictionary class]]) {
        for (NSString *key in [args allKeys]) {
            [url appendString:[NSString stringWithFormat:@"&%@=%@", key, [args objectForKey:key]]];
        }
    }

    return url;
}

When I try to build something like below, the URLs aren't encoded, of course.

NSDictionary *args = [NSDictionary dictionaryWithObjectsAndKeys:
       @"http://other.com", @"url",
       @"ABCDEF", @"apiKey", nil];

NSLog(@"%@", [self urlFor:@"articles" arguments:args]);`

The returned value is http://api.example.com/articles?version=2.0.1&url=http://other.com&apiKey=ABCDEF when it should be http://api.example.com/articles?version=2.0.1&url=http%3A%2F%2Fother.com&apiKey=ABCDEF.

I need to encode both key and value. I searched for something and found CFURLCreateStringByAddingPercentEscapes and stringByAddingPercentEscapesUsingEncoding but none of the tests I made worked.

How can I do it?

+2  A: 

IIRC, slashes should be interpreted properly when they're in the query part of a URL. Did you test to see if it still works without encoded slashses? Otherwise, do something like:

if ([args isKindOfClass:[NSDictionary class]]) {
        for (NSString *key in [args allKeys]) {
            NSString *value = [(NSString*)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)[args objectForKey:key], NULL, CFSTR("/?&:=#"), kCFStringEncodingUTF8) autorelease];
            [url appendString:[NSString stringWithFormat:@"&%@=%@", key, value]];
        }
}

return url;

Note the value of the 4th argument to CFURLCreateStringByAddingPercentEscapes.

Wevah
Nice! Now is working!
Nando Vieira
One question: the 4th argument can accept any character that need to be encoded?
Nando Vieira
Yes. From the documentation:legalURLCharactersToBeEscapedLegal characters to be escaped. Pass NULL to specify that no legal characters be replaced.There are only a few characters that would otherwise not be escaped, but I went the safe route because I was too lazy to look up which ones those were (though it'd probably be a good idea).
Wevah
(I guess formatting doesn't work in comments. Sorry.)
Wevah
+1  A: 

You should consider using Google Toolbox for Mac's GTMNSString+URLArguments; it's designed for exactly this purpose.

smorgan
I'll check GTM. Apparently this library is a good one because every question on SO mentions it.
Nando Vieira