Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse NSURL query property

I have a URL like myApp://action/1?parameter=2&secondparameter=3

With the property query I get following part of my URL

parameter=2&secondparameter=3

Is there any way easy to put this in a NSDictionary or an Array?

Thx a lot

like image 707
gabac Avatar asked Oct 22 '10 14:10

gabac


4 Answers

You can use queryItems in URLComponents.

When you get this property’s value, the NSURLComponents class parses the query string and returns an array of NSURLQueryItem objects, each of which represents a single key-value pair, in the order in which they appear in the original query string.

Swift

let url = "http://example.com?param1=value1&param2=param2"
let queryItems = URLComponents(string: url)?.queryItems
let param1 = queryItems?.filter({$0.name == "param1"}).first
print(param1?.value)

Alternatively, you can add an extension on URL to make things easier.

extension URL {
    var queryParameters: QueryParameters { return QueryParameters(url: self) }
}

class QueryParameters {
    let queryItems: [URLQueryItem]
    init(url: URL?) {
        queryItems = URLComponents(string: url?.absoluteString ?? "")?.queryItems ?? []
        print(queryItems)
    }
    subscript(name: String) -> String? {
        return queryItems.first(where: { $0.name == name })?.value
    }
}

You can then access the parameter by its name.

let url = "http://example.com?param1=value1&param2=param2"
print(url.queryParameters["param1"])
like image 172
Onato Avatar answered Nov 03 '22 14:11

Onato


I had reason to write some extensions for this behavior that might come in handy. First the header:

#import <Foundation/Foundation.h>

@interface NSString (XQueryComponents)
- (NSString *)stringByDecodingURLFormat;
- (NSString *)stringByEncodingURLFormat;
- (NSMutableDictionary *)dictionaryFromQueryComponents;
@end

@interface NSURL (XQueryComponents)
- (NSMutableDictionary *)queryComponents;
@end

@interface NSDictionary (XQueryComponents)
- (NSString *)stringFromQueryComponents;
@end

These methods extend NSString, NSURL, and NSDictionary, to allow you to convert to and from query components strings and dictionary objects containing the results.

Now the related .m code:

#import "XQueryComponents.h"

@implementation NSString (XQueryComponents)
- (NSString *)stringByDecodingURLFormat
{
    NSString *result = [self stringByReplacingOccurrencesOfString:@"+" withString:@" "];
    result = [result stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    return result;
}

- (NSString *)stringByEncodingURLFormat
{
    NSString *result = [self stringByReplacingOccurrencesOfString:@" " withString:@"+"];
    result = [result stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    return result;
}

- (NSMutableDictionary *)dictionaryFromQueryComponents
{
    NSMutableDictionary *queryComponents = [NSMutableDictionary dictionary];
    for(NSString *keyValuePairString in [self componentsSeparatedByString:@"&"])
    {
        NSArray *keyValuePairArray = [keyValuePairString componentsSeparatedByString:@"="];
        if ([keyValuePairArray count] < 2) continue; // Verify that there is at least one key, and at least one value.  Ignore extra = signs
        NSString *key = [[keyValuePairArray objectAtIndex:0] stringByDecodingURLFormat];
        NSString *value = [[keyValuePairArray objectAtIndex:1] stringByDecodingURLFormat];
        NSMutableArray *results = [queryComponents objectForKey:key]; // URL spec says that multiple values are allowed per key
        if(!results) // First object
        {
            results = [NSMutableArray arrayWithCapacity:1];
            [queryComponents setObject:results forKey:key];
        }
        [results addObject:value];
    }
    return queryComponents;
}
@end

@implementation NSURL (XQueryComponents)
- (NSMutableDictionary *)queryComponents
{
    return [[self query] dictionaryFromQueryComponents];
}
@end

@implementation NSDictionary (XQueryComponents)
- (NSString *)stringFromQueryComponents
{
    NSString *result = nil;
    for(__strong NSString *key in [self allKeys])
    {
        key = [key stringByEncodingURLFormat];
        NSArray *allValues = [self objectForKey:key];
        if([allValues isKindOfClass:[NSArray class]])
            for(__strong NSString *value in allValues)
            {
                value = [[value description] stringByEncodingURLFormat];
                if(!result)
                    result = [NSString stringWithFormat:@"%@=%@",key,value];
                else 
                    result = [result stringByAppendingFormat:@"&%@=%@",key,value];
            }
        else {
            NSString *value = [[allValues description] stringByEncodingURLFormat];
            if(!result)
                result = [NSString stringWithFormat:@"%@=%@",key,value];
            else 
                result = [result stringByAppendingFormat:@"&%@=%@",key,value];
        }
    }
    return result;
}
@end
like image 22
BadPirate Avatar answered Nov 03 '22 15:11

BadPirate


Something like that:

NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
for (NSString *param in [url componentsSeparatedByString:@"&"]) {
  NSArray *elts = [param componentsSeparatedByString:@"="];
  if([elts count] < 2) continue;
  [params setObject:[elts lastObject] forKey:[elts firstObject]];
}

Note : This is sample code. All error cases are not managed.

like image 54
Benoît Avatar answered Nov 03 '22 16:11

Benoît


Try this ;)!

NSString *query = @"parameter=2&secondparameter=3"; // replace this with [url query];
NSArray *components = [query componentsSeparatedByString:@"&"];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
for (NSString *component in components) {
    NSArray *subcomponents = [component componentsSeparatedByString:@"="];
    [parameters setObject:[[subcomponents objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
                   forKey:[[subcomponents objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
like image 14
cutsoy Avatar answered Nov 03 '22 16:11

cutsoy