Лучший способ проанализировать строку URL, чтобы получить значения для ключей?
мне нужно разобрать строку URL, как этот:
&ad_eurl=http://www.youtube.com/video/4bL4FI1Gz6s&hl=it_IT&iv_logging_level=3&ad_flags=0&endscreen_module=http://s.ytimg.com/yt/swfbin/endscreen-vfl6o3XZn.swf&cid=241&cust_gender=1&avg_rating=4.82280613104
мне нужно разделить NSString на части signle, такие как cid=241
и &avg_rating=4.82280613104
. Я делал это с substringWithRange:
но значения возвращаются в случайном порядке,так что все портит. Есть ли какой-либо класс, который позволяет легко анализировать, где вы можете в основном преобразовать его в NSDictionary, чтобы иметь возможность читать значение для ключа (например ValueForKey:cid
должен возвратить 241
). Или есть еще один более простой способ разберите его, чем с помощью NSMakeRange
получить подстроку?
15 ответов:
edit (июнь 2018):этот ответ лучше. Apple добавила
NSURLComponents
в iOS 7.Я бы создал словарь, получил массив пар ключ / значение с
NSMutableDictionary *queryStringDictionary = [[NSMutableDictionary alloc] init]; NSArray *urlComponents = [urlString componentsSeparatedByString:@"&"];
затем заполните словарь:
for (NSString *keyValuePair in urlComponents) { NSArray *pairComponents = [keyValuePair componentsSeparatedByString:@"="]; NSString *key = [[pairComponents firstObject] stringByRemovingPercentEncoding]; NSString *value = [[pairComponents lastObject] stringByRemovingPercentEncoding]; [queryStringDictionary setObject:value forKey:key]; }
вы можете запросить с
[queryStringDictionary objectForKey:@"ad_eurl"];
это непроверено, и вы, вероятно, должны сделать еще несколько тестов ошибок.
Я также ответил на это в https://stackoverflow.com/a/26406478/215748.
можно использовать
queryItems
наURLComponents
.при получении значения этого свойства класс NSURLComponents анализирует строку запроса и возвращает массив объектов NSURLQueryItem, каждый из которых представляет одну пару ключ-значение в том порядке, в котором они отображаются в исходной строке запроса.
Swift 3
let url = "http://example.com?param1=value1¶m2=param2" let queryItems = URLComponents(string: url)?.queryItems let param1 = queryItems?.filter({.name == "param1"}).first print(param1?.value)
Swift 2.3
использовать
NSURLComponents
вместоURLComponents
.С
использовать
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; }
Я немного опоздал, но ответов до сих пор не работает как мне нужно. Вы можете использовать этот фрагмент кода:
NSMutableDictionary *queryStrings = [[NSMutableDictionary alloc] init]; for (NSString *qs in [url.query componentsSeparatedByString:@"&"]) { // Get the parameter name NSString *key = [[qs componentsSeparatedByString:@"="] objectAtIndex:0]; // Get the parameter value NSString *value = [[qs componentsSeparatedByString:@"="] objectAtIndex:1]; value = [value stringByReplacingOccurrencesOfString:@"+" withString:@" "]; value = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; queryStrings[key] = value; }
здесь
url
- это URL, который вы хотите обработать. У вас есть все строки запроса, экранированные, вqueryStrings
изменяемый словарь.EDIT: Swift версия:
var queryStrings = [String: String]() if let query = url.query { for qs in query.componentsSeparatedByString("&") { // Get the parameter name let key = qs.componentsSeparatedByString("=")[0] // Get the parameter value var value = qs.componentsSeparatedByString("=")[1] value = value.stringByReplacingOccurrencesOfString("+", withString: " ") value = value.stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding)! queryStrings[key] = value } }
для iOS8 и выше с помощью
NSURLComponents
:+(NSDictionary<NSString *, NSString *> *)queryParametersFromURL:(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; }
для iOS 8 ниже:
+(NSDictionary<NSString *, NSString *> *)queryParametersFromURL:(NSURL *)url NSMutableDictionary<NSString *, NSString *> * parameters = [NSMutableDictionary<NSString *, NSString *> new]; [self enumerateKeyValuePairsFromQueryString:url.query completionblock:^(NSString *key, NSString *value) { parameters[key] = value; }]; return parameters.copy; } - (void)enumerateKeyValuePairsFromQueryString:(NSString *)queryString completionBlock:(void (^) (NSString *key, NSString *value))block { if (queryString.length == 0) { return; } NSArray *keyValuePairs = [queryString componentsSeparatedByString:@"&"]; for (NSString *pair in keyValuePairs) { NSRange range = [pair rangeOfString:@"="]; NSString *key = nil; NSString *value = nil; if (range.location == NSNotFound) { key = pair; value = @""; } else { key = [pair substringToIndex:range.location]; value = [pair substringFromIndex:(range.location + range.length)]; } key = [self decodedStringFromString:key]; key = key ?: @""; value = [self decodedStringFromString:value]; value = value ?: @""; block(key, value); } } + (NSString *)decodedStringFromString:(NSString *)string { NSString *input = shouldDecodePlusSymbols ? [string stringByReplacingOccurrencesOfString:@"+" withString:@" " options:NSLiteralSearch range:NSMakeRange(0, string.length)] : string; return [input stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; }
Если вы хотите сделать то же самое в Swift, вы можете использовать расширение.
extension NSURL { func queryDictionary() -> [String:String] { let components = self.query?.componentsSeparatedByString("&") var dictionary = [String:String]() for pairs in components ?? [] { let pair = pairs.componentsSeparatedByString("=") if pair.count == 2 { dictionary[pair[0]] = pair[1] } } return dictionary } }
Если вы используете
NSURLComponents
следующее краткое расширение также сделает трюк:extension NSURLComponents { func getQueryStringParameter(name: String) -> String? { return (self.queryItems? as [NSURLQueryItem]) .filter({ (item) in item.name == name }).first? .value() } }
этот код работает в трех случаях
1.http://www.youtube.com/watch?v=VWsl7C-y7EI&feature=youtu.be 2.http://youtu.be/lOvcFqQyaDY
3.http://www.youtube.com/watch?v=VWsl7C-y7EINSArray *arr = [youtubeurl componentsSeparatedByString:@"v="]; NSString *youtubeID; if([arr count]>0) { if([arr count]==1){ youtubeID= [[youtubeurl componentsSeparatedByString:@"/"] lastObject]; } else{ NSArray *urlComponents = [[arr objectAtIndex:1] componentsSeparatedByString:@"&"]; youtubeID=[urlComponents objectAtIndex:0]; } }
-(NSArray *)getDataOfQueryString:(NSString *)url{ NSArray *strURLParse = [url componentsSeparatedByString:@"?"]; NSMutableArray *arrQueryStringData = [[NSMutableArray alloc] init]; if ([strURLParse count] < 2) { return arrQueryStringData; } NSArray *arrQueryString = [[strURLParse objectAtIndex:1] componentsSeparatedByString:@"&"]; for (int i=0; i < [arrQueryString count]; i++) { NSMutableDictionary *dicQueryStringElement = [[NSMutableDictionary alloc]init]; NSArray *arrElement = [[arrQueryString objectAtIndex:i] componentsSeparatedByString:@"="]; if ([arrElement count] == 2) { [dicQueryStringElement setObject:[arrElement objectAtIndex:1] forKey:[arrElement objectAtIndex:0]]; } [arrQueryStringData addObject:dicQueryStringElement]; } return arrQueryStringData; }
вы эту функцию просто передать URL и вы получите все элементы querystring.
начиная с iOS 8, вы можете напрямую использовать свойства
name
иvalue
onNSURLQueryItem
.пример, как разобрать URL и получить определенные значения для ключа в разбираемых парах.
NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:@"someURL" resolvingAgainstBaseURL:false]; NSArray *queryItems = urlComponents.queryItems; NSMutableArray *someIDs = [NSMutableArray new]; for (NSURLQueryItem *item in queryItems) { if ([item.name isEqualToString:@"someKey"]) { [someIDs addObject:item.value]; } } NSLog(@"%@", someIDs);
как полная функция:
+ (NSString *)getQueryComponentWithName:(NSString *)name fromURL:(NSURL *)url{ NSString *component = nil; if (url) { NSString *query = url.query; NSMutableDictionary *queryStringDictionary = [NSMutableDictionary dictionary]; NSArray *urlComponents = [query componentsSeparatedByString:@"&"]; for (NSString *keyValuePair in urlComponents){ NSArray *pairComponents = [keyValuePair componentsSeparatedByString:@"="]; NSString *key = [[pairComponents firstObject] stringByRemovingPercentEncoding]; NSString *value = [[pairComponents lastObject] stringByRemovingPercentEncoding]; [queryStringDictionary setObject:value forKey:key]; } component = [queryStringDictionary objectForKey:name]; } return component; } [self getQueryComponentWithName:@"example" fromURL:[NSURL URLWithString:@"https://google.es/?example=test"]];
позднее решение этого в виде расширения Swift 3 на URL
extension URL { func value(for paramater: String) -> String? { let queryItems = URLComponents(string: self.absoluteString)?.queryItems let queryItem = queryItems?.filter({.name == paramater}).first let value = queryItem?.value return value } }
свойство запроса в NSURL даст строку запроса. Затем вы можете проанализировать строку запроса с помощью componentsSeparatedByString
NSArray *parameters = [[url query] componentsSeparatedByString:@"&"]; NSMutableDictionary *keyValuePairs = [NSMutableDictionary dictionary]; for (NSString *eachParam in parameters) { NSArray *QryParts = [eachParam componentsSeparatedByString:@"="]; if ( [QryParts count] == 2 ) { keyValuePairs[QryParts[0]] = QryParts[1]; } else { keyValuePairs[QryParts[0]] = QryParts[0]; } } NSString * name = [keyValuePairs valueForKey:@"name"]; NSString * username = [keyValuePairs valueForKey:@"username"];
- (NSString *)getLoginTokenFromUrl:(NSString *)urlString { NSURL *url = [NSURL URLWithString:urlString]; NSArray *queryStrings = [url.query componentsSeparatedByString:@"&"]; NSMutableDictionary *queryParams = [[NSMutableDictionary alloc] init]; for (NSString *qs in queryStrings) { // Get the parameter name NSArray *components = [qs componentsSeparatedByString:@"="]; NSString *key = [components objectAtIndex:0]; // Get the parameter value NSString *value; if (components.count > 1) { value = [components objectAtIndex:1]; } else { value = @""; } value = [value stringByReplacingOccurrencesOfString:@"+" withString:@" "]; value = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; queryParams[key] = value; } return [queryParams objectForKey:@"login_token"]; }
быстрый 2 подход:
extension NSURL { var queryDictionary: [String: String] { var queryDictionary = [String: String]() guard let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false), queryItems = components.queryItems else { return queryDictionary } queryItems.forEach { queryDictionary[.name] = .value } return queryDictionary } }
чтобы получить параметры запроса в виде dict:
extension URL { var parameters: [String: String] { var parameters = [String: String]() if let urlComponents = URLComponents(url: self, resolvingAgainstBaseURL: false), let queryItems = urlComponents.queryItems { for queryItem in queryItems where queryItem.value != nil { parameters[queryItem.name] = queryItem.value } } return parameters } }
или возвращать необязательно, если это более удобно в вашем случае.