test para pantalla modo informacion herramienta diagnostico diagnostic copiando apple ios objective-c swift parsing cocoa-touch

ios - pantalla - ¿La mejor forma de analizar cadenas URL para obtener valores para las claves?



modo diagnostico iphone (14)

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 el NSString en las partes signle como cid=241 y &avg_rating=4.82280613104 . He estado haciendo esto con substringWithRange: pero los valores vuelven en un orden aleatorio, por lo que lo estropea. ¿Hay alguna clase que permita un análisis sencillo en el que básicamente pueda convertirlo a NSDictionary para poder leer el valor de una clave (por ejemplo, ValueForKey: cid debería devolver 241 ). ¿O hay otra manera más sencilla de analizarlo que utilizar NSMakeRange para obtener una subcadena?


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


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


La propiedad Query en NSURL dará la cadena de consulta. A continuación, puede analizar la cadena de consulta utilizando 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"];


Llego un poco tarde, pero las respuestas proporcionadas hasta ahora no funcionaron como debí. Puedes usar 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; }

Donde url es la URL que quiere analizar. Tiene todas las cadenas de consulta, escapadas, en el diccionario mutable de queryStrings .

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


Para iOS8 y superior con 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]; }


Si desea hacer lo mismo rápidamente, 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 } }


Si está usando NSURLComponents la siguiente extensión concisa también hará el truco:

extension NSURLComponents { func getQueryStringParameter(name: String) -> String? { return (self.queryItems? as [NSURLQueryItem]) .filter({ (item) in item.name == name }).first? .value() } }


También respondí esto en https://.com/a/26406478/215748 .

Puede usar queryItems en URLComponents .

Cuando obtiene el valor de esta propiedad, la clase NSURLComponents analiza la cadena de consulta y devuelve una matriz de objetos NSURLQueryItem, cada uno de los cuales representa un único par clave-valor, en el orden en que aparecen en la cadena de consulta original.

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

Use NSURLComponents lugar de URLComponents .

C objetivo

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


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

Descargar Gist


Una solución tardía a esto en la forma de una extensión de 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 } }

gist


Desde iOS 8, puede usar directamente el name y el value de las NSURLQueryItem en NSURLQueryItem .

Ejemplo, cómo analizar 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);


editar (junio de 2018): esta respuesta es mejor . Apple agregó NSURLComponents en iOS 7 .

Crearía un diccionario, obtendría una matriz de los pares clave / valor con

NSMutableDictionary *queryStringDictionary = [[NSMutableDictionary alloc] init]; NSArray *urlComponents = [urlString componentsSeparatedByString:@"&"];

A continuación, rellene el diccionario:

for (NSString *keyValuePair in urlComponents) { NSArray *pairComponents = [keyValuePair componentsSeparatedByString:@"="]; NSString *key = [[pairComponents firstObject] stringByRemovingPercentEncoding]; NSString *value = [[pairComponents lastObject] stringByRemovingPercentEncoding]; [queryStringDictionary setObject:value forKey:key]; }

A continuación, puede consultar con

[queryStringDictionary objectForKey:@"ad_eurl"];

Esto no se ha probado, y probablemente debería hacer algunas pruebas de error más.


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


-(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 pasa la URL y obtendrás todo el elemento de la cadena de consulta.