views:

595

answers:

5

Hi,

I have an NSURL:

serverCall?x=a&y=b&z=c

What is the quickest and most efficient way to get the value of y?

Thanks

A: 

I'd recommend looking at getResourceValue:forKey:error:. The forKey parameter will be y, I believe.

fbrereto
huh, I just tried this and it didn't work...
Dave DeLong
This appears to only work on OSX, not iPhone.
Dave
+2  A: 

I'm pretty sure you have to parse it yourself. However, it's not too bad:

NSString * q = [myURL query];
NSArray * pairs = [q componentsSeparatedByString:@"&"];
NSMutableDictionary * kvPairs = [NSMutableDictionary dictionary];
for (NSString * pair in pairs) {
  NSArray * bits = [pair componentsSeparatedByString:@"="];
  NSString * key = [[bits objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
  NSString * value = [[bits objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
  [kvPairs setObject:value forKey:key];
}

NSLog(@"y = %@", [kvPairs objectForKey:@"y"]);
Dave DeLong
+4  A: 

Well I know you said "the quickest way" but after I started doing a test with NSScanner I just couldn't stop. And while it is not the shortest way, it is sure handy if you are planning to use that feature a lot. I created a URLParser class that gets these vars using an NSScanner. The use is a simple as:

URLParser *parser = [[[URLParser alloc] initWithURLString:@"http://blahblahblah.com/serverCall?x=a&y=b&z=c&flash=yes"] autorelease];
NSString *y = [parser valueForVariable:@"y"];
NSLog(@"%@", y); //b
NSString *a = [parser valueForVariable:@"a"];
NSLog(@"%@", a); //(null)
NSString *flash = [parser valueForVariable:@"flash"];
NSLog(@"%@", flash); //yes

And the class that does this is the following (*source files at the bottom of the post):

URLParser.h

@interface URLParser : NSObject {
    NSArray *variables;
}

@property (nonatomic, retain) NSArray *variables;

- (id)initWithURLString:(NSString *)url;
- (NSString *)valueForVariable:(NSString *)varName;

@end

URLParser.m

@implementation URLParser
@synthesize variables;

- (id) initWithURLString:(NSString *)url{
    self = [super init];
    if (self != nil) {
        NSString *string = url;
        NSScanner *scanner = [NSScanner scannerWithString:string];
        [scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@"&?"]];
        NSString *tempString;
        NSMutableArray *vars = [NSMutableArray new];
        [scanner scanUpToString:@"?" intoString:nil];       //ignore the beginning of the string and skip to the vars
        while ([scanner scanUpToString:@"&" intoString:&tempString]) {
            [vars addObject:[tempString copy]];
        }
        self.variables = vars;
        [vars release];
    }
    return self;
}

- (NSString *)valueForVariable:(NSString *)varName {
    for (NSString *var in self.variables) {
        if ([var length] > [varName length]+1 && [[var substringWithRange:NSMakeRange(0, [varName length]+1)] isEqualToString:[varName stringByAppendingString:@"="]]) {
            NSString *varValue = [var substringFromIndex:[varName length]+1];
            return varValue;
        }
    }
    return nil;
}

- (void) dealloc{
    self.variables = nil;
    [super dealloc];
}

@end

*if you don't like copying and pasting you can just download the source files - I made a quick blog post about this here.

Dimitris
+1 for awesomeness! `NSScanner` is a class that I haven't played with much, and this looks really interesting. The only comment I'd say is to not call the method `getValue...`. That implies (according to convention) that you're going to be returning the value via an out parameter. `valueForVariable:` would be the proper name.
Dave DeLong
I haven't played with `NSScanner` before either so I figured this a nice task to test it with. As for the method name, I didn't like it either but it was 2:00am and wanted to wrap things up :P It's updated.
Dimitris
A: 

Quickest is:

NSString* x = [url valueForQueryParameterKey:@"x"];
Malcolm Hall
A: 

NSString* x = [url valueForQueryParameterKey:@"x"];

The above format doesn't seem to work. Is there anything else that needs to be done to make that work? It throws this exception: "NSString* x = [url valueForQueryParameterKey:@"x"];"

mdominick