parsingNSURL查询属性

我有一个像myApp://action/1?parameter=2&secondparameter=3的URL

随着属性查询,我得到了我的URL一部分

 parameter=2&secondparameter=3 

有什么方法可以很容易地把它放在一个NSDictionary或一个Array

多谢

类似的东西:

 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]]; } 

注意 :这是示例代码。 所有错误情况都不受pipe理。

您可以在URLComponents使用queryItems

获取此属性的值时,NSURLComponents类将parsing查询string,并按照它们在原始查询string中的显示顺序返回一个NSURLQueryItem对象数组,每个对象表示一个键 – 值对。

Swift 3

 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) 

Swift 2.3

使用NSURLComponents而不是URLComponents

目标C

使用NSURLComponents

 NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; NSArray *queryItems = urlComponents.queryItems; NSString *param1 = [self valueForKey:@"param1" fromQueryItems:queryItems]; NSLog(@"%@", param1); … - (NSString *)valueForKey:(NSString *)key fromQueryItems:(NSArray *)queryItems { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name=%@", key]; NSURLQueryItem *queryItem = [[queryItems filteredArrayUsingPredicate:predicate] firstObject]; return queryItem.value; } 

我有理由写这个行为的一些扩展,可能会派上用场。 首先标题:

 #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 

这些方法扩展了NSString,NSURL和NSDictionary,使您可以转换查询组件string和包含结果的字典对象。

现在相关的.m代码:

 #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 

尝试这个 ;)!

 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]]; } 

所有以前的post都没有正确的做url编码。 我会build议以下方法:

 +(NSString*)concatenateQuery:(NSDictionary*)parameters { if([parameters count]==0) return nil; NSMutableString* query = [NSMutableString string]; for(NSString* parameter in [parameters allKeys]) [query appendFormat:@"&%@=%@",[parameter stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet],[[parameters objectForKey:parameter] stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]]; return [[query substringFromIndex:1] copy]; } +(NSDictionary*)splitQuery:(NSString*)query { if([query length]==0) return nil; NSMutableDictionary* parameters = [NSMutableDictionary dictionary]; for(NSString* parameter in [query componentsSeparatedByString:@"&"]) { NSRange range = [parameter rangeOfString:@"="]; if(range.location!=NSNotFound) [parameters setObject:[[parameter substringFromIndex:range.location+range.length] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] forKey:[[parameter substringToIndex:range.location] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; else [parameters setObject:[[NSString alloc] init] forKey:[parameter stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; } return [parameters copy]; } 

这里是快速的扩展:

 extension NSURL{ func queryParams() -> [String:AnyObject] { var info : [String:AnyObject] = [String:AnyObject]() if let queryString = self.query{ for parameter in queryString.componentsSeparatedByString("&"){ let parts = parameter.componentsSeparatedByString("=") if parts.count > 1{ let key = (parts[0] as String).stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding) let value = (parts[1] as String).stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding) if key != nil && value != nil{ info[key!] = value } } } } return info } } 

根据已经非常干净的Onato答案,我写了一个扩展NSURL在Swift中,你可以得到一个查询参数是这样的:

例如,URL包含param = some_value对

 let queryItem = url.queryItemForKey("param") let value = queryItem.value // would get String "someValue" 

扩展名如下所示:

 extension NSURL { var allQueryItems: [NSURLQueryItem] { get { let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false)! let allQueryItems = components.queryItems! return allQueryItems as [NSURLQueryItem] } } func queryItemForKey(key: String) -> NSURLQueryItem? { let predicate = NSPredicate(format: "name=%@", key)! return (allQueryItems as NSArray).filteredArrayUsingPredicate(predicate).first as? NSURLQueryItem } } 

对于那些使用Bolts框架,你可以使用:

 NSDictionary *parameters = [BFURL URLWithURL:yourURL].inputQueryParameters; 

记得导入:

 #import <Bolts/BFURL.h> 

如果您的项目中恰好有Facebook SDK ,则还有Bolts 。 Facebook正在使用这个框架作为依赖。

处理URL的首选方法是NSURLComponents 。 特别是返回一个NSArray params的queryItems属性。

如果你想在一个NSDictionary的参数,这里是一个方法:

 +(NSDictionary<NSString *, NSString *>*)queryParamsFromURL:(NSURL*)url { NSURLComponents* urlComponents = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; NSMutableDictionary<NSString *, NSString *>* queryParams = [NSMutableDictionary<NSString *, NSString *> new]; for (NSURLQueryItem* queryItem in [urlComponents queryItems]) { if (queryItem.value == nil) { continue; } [queryParams setObject:queryItem.value forKey:queryItem.name]; } return queryParams; } 

注意:URL可以有重复的参数,但是字典只包含任何重复参数的最后一个值。 如果这是不可取的,请直接使用queryItems数组。

Swift 2.1

Oneliner:

 "p1=v1&p2=v2".componentsSeparatedByString("&").map { $0.componentsSeparatedByString("=") }.reduce([:]) { (var dict: [String:String], p) in dict[p[0]] = p[1] return dict } // ["p1": "v1", "p2": "v2"] 

用作NSURL的扩展:

 extension NSURL { /** * URL query string as dictionary. Empty dictionary if query string is nil. */ public var queryValues : [String:String] { get { if let q = self.query { return q.componentsSeparatedByString("&").map { $0.componentsSeparatedByString("=") }.reduce([:]) { (var dict: [String:String], p) in dict[p[0]] = p[1] return dict } } else { return [:] } } } } 

例:

 let url = NSURL(string: "http://example.com?p1=v1&p2=v2")! let queryDict = url.queryValues // ["p1": "v1", "p2": "v2"] 

请注意,如果使用OS X 10.10或iOS 8(或更高版本),最好使用NSURLComponentsqueryItems属性,并直接从NSURLQueryItems创build字典。

这是一个基于NSURLComponentsNSURL扩展解决scheme:

 extension NSURL { /// URL query string as a dictionary. Empty dictionary if query string is nil. public var queryValues : [String:String] { get { guard let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false) else { return [:] } guard let queryItems = components.queryItems else { return [:] } var result:[String:String] = [:] for q in queryItems { result[q.name] = q.value } return result } } } 

NSURL扩展的脚注是,它实际上可能在Swift中为该属性赋予与现有string属性query相同的名称。 我直到我尝试了才知道,但Swift中的多态性只允许你在返回types上有所不同。 所以如果扩展的NSURL属性是public var query: [String:String]它的作品。 我没有使用这个例子,因为我觉得有点疯狂,但它确实有效。

我在MIT发表了一个简单的课,

https://github.com/anegmawad/URLQueryToCocoa

有了它,你可以在查询中有数组和对象,这些数据和对象被收集并粘在一起

例如

 users[0][firstName]=Amin&users[0][lastName]=Negm&name=Devs&users[1][lastName]=Kienle&users[1][firstName]=Christian 

会变成:

 @{ name : @"Devs", users : @[ @{ firstName = @"Amin", lastName = @"Negm" }, @{ firstName = @"Christian", lastName = @"Kienle" } ] } 

你可以把它看作NSJSONSerializer的URL查询对象。

看起来您正在使用它来处理来自另一个iOS应用程序的传入数据。 如果是这样,这是我用于相同的目的。

初始呼叫(如在外部应用程序中):

 UIApplication *application = [UIApplication sharedApplication]; NSURL *url = [NSURL URLWithString:@"myApp://action/1?parameter=2&secondparameter=3"]; if ([application canOpenURL:url]) { [application openURL:url]; NSLog(@"myApp is installed"); } else { NSLog(@"myApp is not installed"); } 

从NSURL中提取QueryString数据并保存为NSDictionary的方法:

 -(NSDictionary *) getNSDictionaryFromQueryString:(NSURL *)url { NSMutableDictionary *result = [[NSMutableDictionary alloc] init]; NSRange needle = [url.absoluteString rangeOfString:@"?" options:NSCaseInsensitiveSearch]; NSString *data = nil; if(needle.location != NSNotFound) { NSUInteger start = needle.location + 1; NSUInteger end = [url.absoluteString length] - start; data = [url.absoluteString substringWithRange:NSMakeRange(start, end)]; } for (NSString *param in [data componentsSeparatedByString:@"&"]) { NSArray *keyvalue = [param componentsSeparatedByString:@"="]; if([keyvalue count] == 2){ [result setObject:[keyvalue objectAtIndex:1] forKey:[keyvalue objectAtIndex:0]]; } } return result; } 

用法:

 NSDictionary *result = [self getNSDictionaryFromQueryString:url]; 

这个类是parsingURL的一个很好的解决scheme。

.h文件

 @interface URLParser : NSObject { NSArray *variables; } @property (nonatomic, retain) NSArray *variables; - (id)initWithURLString:(NSString *)url; - (NSString *)valueForVariable:(NSString *)varName; @end 

.m文件

 #import "URLParser.h" @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; } 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; } @end 

Hendrik在这个问题中为扩展写了一个很好的例子,但是我不得不重写它来不使用任何objective-c库方法。 在swift中使用NSArray不是正确的方法。

这就是结果,所有这些都是迅速而安全的。 这个用法示例将使用Swift 1.2的更less的代码行。

 public extension NSURL { /* Set an array with all the query items */ var allQueryItems: [NSURLQueryItem] { get { let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false)! if let allQueryItems = components.queryItems { return allQueryItems as [NSURLQueryItem] } else { return [] } } } /** Get a query item form the URL query :param: key The parameter to fetch from the URL query :returns: `NSURLQueryItem` the query item */ public func queryItemForKey(key: String) -> NSURLQueryItem? { let filteredArray = filter(allQueryItems) { $0.name == key } if filteredArray.count > 0 { return filteredArray.first } else { return nil } } } 

用法:

 let queryItem = url.queryItemForKey("myItem") 

或者,更详细的用法:

 if let url = NSURL(string: "http://www.domain.com/?myItem=something") { if let queryItem = url.queryItemForKey("myItem") { if let value = queryItem.value { println("The value of 'myItem' is: \(value)") } } } 

尝试这个:

 -(NSDictionary *)getUrlParameters:(NSString *)url{ NSArray *justParamsArr = [url componentsSeparatedByString:@"?"]; url = [justParamsArr lastObject]; 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]]; } return params; } 

如果您正在使用URL将数据从Web应用程序传递到手机,并且您想传递数组,数字,string…

JSON在PHP中编码你的对象

 header("Location: myAppAction://".urlencode(json_encode($YOUROBJECT))); 

JSON在iOS中解码结果

 NSData *data = [[[request URL] host] dataUsingEncoding:NSUTF8StringEncoding]; NSDictionary *packed = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];