У меня есть URL типа myApp://action/1?parameter=2&secondparameter=3
С запросом свойства я получаю следующую часть моего URL
parameter=2&secondparameter=3
Есть ли способ легко поместить это в NSDictionary
или в Array
?
Большое спасибо
iphone
objective-c
nsurl
габак
источник
источник
[params setObject:[elts lastObject] forKey:[elts firstObject]];
он более безопасенВы можете использовать
queryItems
вURLComponents
.Swift
let url = "http://example.com?param1=value1¶m2=param2" let queryItems = URLComponents(string: url)?.queryItems let param1 = queryItems?.filter({$0.name == "param1"}).first print(param1?.value)
Кроме того, вы можете добавить расширение к URL-адресу, чтобы упростить задачу.
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 } }
Затем вы можете получить доступ к параметру по его имени.
let url = "http://example.com?param1=value1¶m2=param2" print(url.queryParameters["param1"])
источник
http://example.com/abc#abc?param1=value1¶m2=param2
queryItems будет равен нулюУ меня была причина написать несколько расширений для этого поведения, которые могли бы пригодиться. Сначала заголовок:
#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, чтобы вы могли преобразовывать в и из строк компонентов запроса и объектов словаря, содержащих результаты.
Теперь связанный код .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]]; }
источник
Все предыдущие сообщения неправильно кодируют URL. Я бы предложил следующие методы:
+(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]; }
источник
if(!query||[query length] == 0)
избыточно. Вы можете смело проверять, такif([query length] == 0)
как в этом случаеquery == nil
он вернет значение,0
если вы попытаетесь вызвать length.NSUTF8StringEncoding
insplitQuery
для поддержки всех кодировок :) Кроме того,[string stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]
это новый способ кодирования дляconcatenateQuery
.Вот быстрое расширение:
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 } }
источник
Согласно уже очень чистому ответу Онато, я написал расширение для 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 Framework, вы можете использовать:
NSDictionary *parameters = [BFURL URLWithURL:yourURL].inputQueryParameters;
Не забудьте импортировать:
#import <Bolts/BFURL.h>
Если в вашем проекте есть Facebook SDK , у вас также есть Bolts . Facebook использует эту структуру как зависимость.
источник
BFURL(url: url)?.inputQueryParameters?["myKey"] as? String
Предпочтительный способ работы с URL-адресами - сейчас
NSURLComponents
. В частности,queryItems
свойство, которое возвращаетNSArray
из params.Если вам нужны параметры в a
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
Один лайнер:
"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 (или более поздней версии), это, вероятно , лучше использовать
NSURLComponents
иqueryItems
свойство и создать словарь изNSURLQueryItems
непосредственно.Вот на
NSURLComponents
основеNSURL
решения расширения: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 можно дать свойству то же имя, что и существующее строковое свойство -
query
. Я не знал, пока не попробовал, но полиморфизм в Swift позволяет отличаться только типом возвращаемого значения. Итак, если расширенное свойство 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" } ] }
Вы можете думать об этом как о аналоге URL-запроса
NSJSONSerializer
.источник
Похоже, вы используете его для обработки входящих данных из другого приложения 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"); }
Метод извлечения данных QueryString из NSURL и сохранения как 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];
источник
Этот класс - хорошее решение для парсинга URL.
.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
источник
Хендрик написал хороший пример расширения в этом вопросе, однако мне пришлось переписать его, чтобы не использовать какие-либо методы библиотеки objective-c. Использование
NSArray
в swift - неправильный подход.Это результат, все быстро и немного безопаснее. Пример использования будет меньше строк кода с Swift 1.2.
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; }
источник
Достаточно компактный подход:
func stringParamsToDict(query: String) -> [String: String] { let params = query.components(separatedBy: "&").map { $0.components(separatedBy: "=") }.reduce(into: [String: String]()) { dict, pair in if pair.count == 2 { dict[pair[0]] = pair[1] } } return params }
источник
Наиболее надежное решение, если вы используете URL-адрес для передачи данных из веб-приложения на телефон и хотите передавать массивы, числа, строки и т. Д.
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];
источник