Necesito analizar una cadena de URL como esta:
&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
Necesito dividir NSString en partes signle como cid=241
y &avg_rating=4.82280613104
. He estado haciendo esto con substringWithRange:
pero los valores regresan en un orden aleatorio, así que eso lo estropea. ¿Existe alguna clase que permita un análisis fácil donde básicamente pueda convertirlo a NSDictionary para poder leer el valor de una clave (por ejemplo, ValueForKey: cid
debería regresar 241
)? ¿O hay otra forma más fácil de analizarlo que usarlo NSMakeRange
para obtener una subcadena?
fuente
NSArray *urlComponents = [urlString componentsSeparatedByString:@"&"]; NSMutableDictionary *queryStringDictionary = [[NSMutableDictionary alloc] initWithCapacity: urlComponents.count];
NSRange range = [keyValuePair rangeOfString:@"="]; NSString *key = [keyValuePair substringToIndex:range.location]; NSString *value = [keyValuePair substringFromIndex:range.location+1];
También respondí esto en https://stackoverflow.com/a/26406478/215748 .
Puede usar
queryItems
enURLComponents
.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)
Alternativamente, puede agregar una extensión en la URL para facilitar las cosas.
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 } }
A continuación, puede acceder al parámetro por su nombre.
let url = URL(string: "http://example.com?param1=value1¶m2=param2")! print(url.queryParameters["param1"])
fuente
Llego un poco tarde, pero las respuestas proporcionadas hasta ahora no funcionaron como necesitaba. Puede utilizar este fragmento de código:
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; }
¿Dónde
url
está la URL que desea analizar? Tiene todas las cadenas de consulta, escapadas, en elqueryStrings
diccionario mutable.EDITAR : Versión 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 } }
fuente
=
utilizado para el relleno no aparecería como=
hasta que se decodificara al final. Sin embargo, no admite parámetros de consulta sin un valor.http://example.org/?base64=ZGF0YT1bMTUyLCAyNDI2LCAyMzE1XQ==
con el código de respuesta. VolveráZGF0YT1bMTUyLCAyNDI2LCAyMzE1XQ
noZGF0YT1bMTUyLCAyNDI2LCAyMzE1XQ==
. Por supuesto, algunos decodificadores base64 decodifican correctamente, pero, por ejemplo,NSData initWithBase64EncodedString:options:
devuelven una cadena vacía sin relleno=
. Por lo tanto, debe tener cuidado cuando maneje la cadena base64 con el código de respuesta.http://example.org/?base64=ZGF0YT1bMTUyLCAyNDI2LCAyMzE1XQ==
, seríahttp://example.org/?base64=ZGF0YT1bMTUyLCAyNDI2LCAyMzE1XQ%3D%3D
como el valor debería estar codificado como urlPara iOS8 y superior usando
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; }
Para iOS 8 a continuación:
+(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]; }
fuente
Si desea hacer lo mismo en Swift, puede usar una extensión.
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 } }
fuente
Si está utilizando
NSURLComponents
la siguiente extensión concisa también funcionará:extension NSURLComponents { func getQueryStringParameter(name: String) -> String? { return (self.queryItems? as [NSURLQueryItem]) .filter({ (item) in item.name == name }).first? .value() } }
fuente
func getQueryStringParameter(name: String) -> String? { return self.queryItems?.filter({ (item) in item.name == name }).first?.value }
Desde iOS 8 puede usar propiedades directamente
name
y asívalue
sucesivamenteNSURLQueryItem
.Ejemplo, cómo analizar la URL y obtener valores específicos para una clave en pares analizados.
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);
fuente
Rápido 5
extension URL { func queryParams() -> [String:String] { let queryItems = URLComponents(url: self, resolvingAgainstBaseURL: false)?.queryItems let queryTuples: [(String, String)] = queryItems?.compactMap{ guard let value = $0.value else { return nil } return ($0.name, value) } ?? [] return Dictionary(uniqueKeysWithValues: queryTuples) } }
fuente
Este código funciona en tres casos.
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-y7EI
NSArray *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]; } }
fuente
-(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; }
Esta función solo tiene que pasar URL y obtendrá todo el elemento de la cadena de consulta.
fuente
Una solución tardía a esto en forma de una extensión Swift 3 en URL
extension URL { func value(for paramater: String) -> String? { let queryItems = URLComponents(string: self.absoluteString)?.queryItems let queryItem = queryItems?.filter({$0.name == paramater}).first let value = queryItem?.value return value } }
esencia
fuente
Como función completa:
+ (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"]];
fuente
Para obtener los parámetros de consulta como un dictado:
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 } }
o devolver Opcional si esta más conveniente en tu caso.
fuente
La propiedad de consulta en NSURL proporcionará la cadena de consulta. Luego puede analizar la cadena de consulta usando 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"];
fuente
- (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"]; }
fuente
Un enfoque Swift 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[$0.name] = $0.value } return queryDictionary } }
Descarga Gist
fuente