Are there any standard objects or functions to parse an NSURL's components? Clearly I could write one, but why re-invent the wheel?
[NSURL path]
will return an NSString
like "argX=x&argY=y&argZ=z"
What I would rather get back is a dictionary populated with {@"argX" => @"x", @"argY" => @"y", @"argZ" = @"z"}
For the path, which returns a string like "/partA/partB/partC", I would rather get an array with the structure {[0] => @"partA", [1] => @"partB", [2] => @"partC"}
I realize this is a pretty specific ask, but it seems like something a lot of people would want.
This is for iOS! Apparently NSURL has different functions on macOS.
Alright, I got antsy and wrote a solution for extending NSString through Categories. I haven't tested this yet, but if you want to use it, go for it.
@interface NSString (ParseCategory)
- (NSMutableDictionary *)explodeToDictionaryInnerGlue:(NSString *)innerGlue outterGlue:(NSString *)outterGlue;
@end
@implementation NSString (ParseCategory)
- (NSMutableDictionary *)explodeToDictionaryInnerGlue:(NSString *)innerGlue outterGlue:(NSString *)outterGlue {
// Explode based on outter glue
NSArray *firstExplode = [self componentsSeparatedByString:outterGlue];
NSArray *secondExplode;
// Explode based on inner glue
NSInteger count = [firstExplode count];
NSMutableDictionary *returnDictionary = [NSMutableDictionary dictionaryWithCapacity:count];
for (NSInteger i = 0; i < count; i++) {
secondExplode = [(NSString *)[firstExplode objectAtIndex:i] componentsSeparatedByString:innerGlue];
if ([secondExplode count] == 2) {
[returnDictionary setObject:[secondExplode objectAtIndex:1] forKey:[secondExplode objectAtIndex:0]];
}
}
return returnDictionary;
}
@end
It's called like this:
NSMutableDictionary *parsedQuery = [[myNSURL query] explodeToDictionaryInnerGlue:@"=" outterGlue=@"&"]
For parsing the path portion of the NSURL (ie @"/partA/partB/partC"), just call this:
NSArray *parsedPath = [[nyNSURL path] componentsSeperatedByString:@"/"];
Be aware that parsedPath[0] will be an empty string because of the leading /!
EDIT - Here is a Category extension to NSURL for your usage pleasure. It strips the initial "/" so you don't have an empty 0 index.
@implementation NSURL (ParseCategory)
- (NSArray *)pathArray {
// Create a character set for the slash character
NSRange slashRange;
slashRange.location = (unsigned int)'/';
slashRange.length = 1;
NSCharacterSet *slashSet = [NSCharacterSet characterSetWithRange:slashRange];
// Get path with leading (and trailing) slashes removed
NSString *path = [[self path] stringByTrimmingCharactersInSet:slashSet];
return [path componentsSeparatedByCharactersInSet:slashSet];
}
- (NSDictionary *)queryDictionary {
NSDictionary *returnDictionary = [[[[self query] explodeToDictionaryInnerGlue:@"=" outterGlue:@"&"] copy] autorelease];
return returnDictionary;
}
@end
Sam Soffes created a well maintained Category for NSURL / NSDictionary. It can be found here: https://github.com/samsoffes/sstoolkit/
You might want to look at pathComponents
which returns an array of the components of the URL. Get more information here.
Heres what i use to parse the query string
// Parse the individual parameters
// parameters = @"hello=world&foo=bar";
NSMutableDictionary *dictParameters = [[NSMutableDictionary alloc] init];
NSArray *arrParameters = [parameters componentsSeparatedByString:@"&"];
for (int i = 0; i < [arrParameters count]; i++) {
NSArray *arrKeyValue = [[arrParameters objectAtIndex:i] componentsSeparatedByString:@"="];
if ([arrKeyValue count] >= 2) {
NSMutableString *strKey = [NSMutableString stringWithCapacity:0];
[strKey setString:[[[arrKeyValue objectAtIndex:0] lowercaseString] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
NSMutableString *strValue = [NSMutableString stringWithCapacity:0];
[strValue setString:[[[arrKeyValue objectAtIndex:1] stringByReplacingOccurrencesOfString:@"+" withString:@" "] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
if (strKey.length > 0) [dictParameters setObject:strValue forKey:strKey];
}
}
NSLog(@"Parameters: %@", dictParameters);
If you do decide to write one (I'm not sure there are existing methods of getting the components you want), you might want to use NSString's componentsSeparatedByString
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With