1

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) {
            [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?

1
  • Sorry! My code broke the syntax highlighting and I can't fix it! Anyone? Commented Aug 9, 2009 at 0:07

3 Answers 3

3

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]];
            [value release];
        }
}

return url;

Note the value of the 4th argument to CFURLCreateStringByAddingPercentEscapes.

Sign up to request clarification or add additional context in comments.

6 Comments

One question: the 4th argument can accept any character that need to be encoded?
Yes. From the documentation: legalURLCharactersToBeEscaped Legal 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).
This leaks memory. value is an owned object that is discarded without being released.
You're right; I'll edit it. Can't believe I blitzed that out…
This is actually bad code (as of now). I think the memory stuff is a bit messed up. Check out this question for better/updated code: stackoverflow.com/questions/718429/…
|
1

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

1 Comment

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

I'd recommend our KSFileUtilities set of classes. Your example would then be:

- (NSString *)urlFor:(NSString *)path arguments:(NSDictionary *)args
{
    NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithDictionary:args];
    [parameters setObject:@"2.0.1" forKey:@"version"];

    NSURL *result = [NSURL ks_URLWithScheme:@"http"
                                       host:@"api.example.com"
                                       path:path
                            queryParameters:parameters;

    return [result absoluteString];
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.