NSURL estrae un singolo valore per una chiave in una stringa di parametri

Ho un NSURL:

serverCall? x = y = a & b & z = c

Qual è il modo più rapido ed efficace per ottenere il valore di y?

Grazie

AGGIORNARE:

Dal 2010, quando questo è stato scritto, sembra che Apple abbia rilasciato una serie di strumenti per questo scopo. Si prega di vedere le risposte qui sotto per quelli.

Soluzione vecchia scuola:

Beh, so che hai detto ” il modo più veloce “, ma dopo aver iniziato a fare un test con NSScanner non sono riuscito a fermarmi. E anche se non è la via più breve, è sicuramente utile se stai pianificando di utilizzare questa funzionalità molto. Ho creato una class URLParser che ottiene questi vars utilizzando un NSScanner . L’uso è semplice come:

 URLParser *parser = [[[URLParser alloc] initWithURLString:@"http://blahblahblah.com/serverCall?x=a&y=b&z=c&flash=yes"] autorelease]; NSString *y = [parser valueForVariable:@"y"]; NSLog(@"%@", y); //b NSString *a = [parser valueForVariable:@"a"]; NSLog(@"%@", a); //(null) NSString *flash = [parser valueForVariable:@"flash"]; NSLog(@"%@", flash); //yes 

E la class che fa questo è la seguente (* file sorgente in fondo al post):

URLParser.h

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

URLParser.m

 @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; [vars release]; } 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; } - (void) dealloc{ self.variables = nil; [super dealloc]; } @end 

* se non ti piace copiare e incollare puoi semplicemente scaricare i file sorgente – ho fatto un breve post sul blog qui .

Così tanti parser di url personalizzati qui, ricorda che NSURLComponents è tuo amico!

Ecco un esempio in cui estraggo un parametro con codifica url per “pagina”

veloce

 let myURL = "www.something.com?page=2" var pageNumber : Int? if let queryItems = NSURLComponents(string: myURL)?.queryItems { for item in queryItems { if item.name == "page" { if let itemValue = item.value { pageNumber = Int(itemValue) } } } } print("Found page number: \(pageNumber)") 

Objective-C

 NSString *myURL = @"www.something.com?page=2"; NSURLComponents *components = [NSURLComponents componentsWithString:myURL]; NSNumber *page = nil; for(NSURLQueryItem *item in components.queryItems) { if([item.name isEqualToString:@"page"]) page = [NSNumber numberWithInteger:item.value.integerValue]; } 

“Perché reinventare la ruota!” – Qualcuno intelligente

Sono abbastanza sicuro che devi analizzarlo da solo. Tuttavia, non è male:

 NSString * q = [myURL query]; NSArray * pairs = [q componentsSeparatedByString:@"&"]; NSMutableDictionary * kvPairs = [NSMutableDictionary dictionary]; for (NSString * pair in pairs) { NSArray * bits = [pair componentsSeparatedByString:@"="]; NSString * key = [[bits objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSString * value = [[bits objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; [kvPairs setObject:value forKey:key]; } NSLog(@"y = %@", [kvPairs objectForKey:@"y"]); 

In Swift è ansible utilizzare NSURLComponents per analizzare la stringa di query di un NSURL in un object [AnyObject].

È quindi ansible creare un dizionario da esso (o accedere direttamente agli elementi) per ottenere le coppie chiave / valore. Ad esempio questo è quello che sto usando per analizzare un url della variabile NSURL:

 let urlComponents = NSURLComponents(URL: url, resolvingAgainstBaseURL: false) let items = urlComponents?.queryItems as [NSURLQueryItem] var dict = NSMutableDictionary() for item in items{ dict.setValue(item.value, forKey: item.name) } println(dict["x"]) 

Ho usato questa categoria: https://github.com/carlj/NSURL-Parameters .

È piccolo e facile da usare:

 #import "NSURL+Parameters.h" ... NSURL *url = [NSURL URLWithString:@"http://foo.bar.com?paramA=valueA&paramB=valueB"]; NSString *paramA = url[@"paramA"]; NSString *paramB = url[@"paramB"]; 

Puoi utilizzare Google Toolbox per Mac. Aggiunge una funzione a NSString per convertire una stringa di query in un dizionario.

http://code.google.com/p/google-toolbox-for-mac/

Esso funziona magicamente

  NSDictionary * d = [NSDictionary gtm_dictionaryWithHttpArgumentsString:[[request URL] query]]; 

Ecco un’estensione Swift 2.0 che fornisce un accesso semplice ai parametri:

 extension NSURL { var params: [String: String] { get { let urlComponents = NSURLComponents(URL: self, resolvingAgainstBaseURL: false) var items = [String: String]() for item in urlComponents?.queryItems ?? [] { items[item.name] = item.value ?? "" } return items } } } 

Esempio di utilizzo:

 let url = NSURL(string: "http://google.com?test=dolphins") if let testParam = url.params["test"] { print("testParam: \(testParam)") } 

Ho scritto una semplice categoria per estendere NSString / NSURL che consente di estrarre i parametri di query URL singolarmente o come dizionario di coppie chiave / valore:

https://github.com/nicklockwood/RequestUtils

L’ho fatto usando un metodo di categoria basato sulla soluzione @Dimitris

 #import "NSURL+DictionaryValue.h" @implementation NSURL (DictionaryValue) -(NSDictionary *)dictionaryValue { NSString *string = [[self.absoluteString stringByReplacingOccurrencesOfString:@"+" withString:@" "] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSScanner *scanner = [NSScanner scannerWithString:string]; [scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@"&?"]]; NSString *temp; NSMutableDictionary *dict = [[[NSMutableDictionary alloc] init] autorelease]; [scanner scanUpToString:@"?" intoString:nil]; //ignore the beginning of the string and skip to the vars while ([scanner scanUpToString:@"&" intoString:&temp]) { NSArray *parts = [temp componentsSeparatedByString:@"="]; if([parts count] == 2) { [dict setObject:[parts objectAtIndex:1] forKey:[parts objectAtIndex:0]]; } } return dict; } @end 

Ti consiglio di consultare getResourceValue:forKey:error: Il parametro forKey sarà y , credo.

Puoi farlo facilmente:

 - (NSMutableDictionary *) getUrlParameters:(NSURL *) url { NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; NSString *tmpKey = [url query]; for (NSString *param in [[url query] componentsSeparatedByString:@"="]) { if ([tmpKey rangeOfString:param].location == NSNotFound) { [params setValue:param forKey:tmpKey]; tmpKey = nil; } tmpKey = param; } [tmpKey release]; return params; } 

Restituisce un dizionario simile: Chiave = valore

Ho modificato leggermente il codice di Dimitris per una migliore gestione ed efficienza della memoria. Inoltre, funziona in ARC.

URLParser.h

 @interface URLParser : NSObject - (void)setURLString:(NSString *)url; - (NSString *)valueForVariable:(NSString *)varName; @end 

URLParser.m

 #import "URLParser.h" @implementation URLParser { NSMutableDictionary *_variablesDict; } - (void)setURLString:(NSString *)url { [_variablesDict removeAllObjects]; NSString *string = url; NSScanner *scanner = [NSScanner scannerWithString:string]; [scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@"&?"]]; NSString *tempString; [scanner scanUpToString:@"?" intoString:nil]; //ignore the beginning of the string and skip to the vars while ([scanner scanUpToString:@"&" intoString:&tempString]) { NSString *dataString = [tempString copy]; NSArray *sepStrings = [dataString componentsSeparatedByString:@"="]; if ([sepStrings count] == 2) { [_variablesDict setValue:sepStrings[1] forKeyPath:sepStrings[0]]; } } } - (id)init { self = [super init]; if (self) { _variablesDict = [[NSMutableDictionary alloc] init]; } return self; } - (NSString *)valueForVariable:(NSString *)varName { NSString *val = [_variablesDict valueForKeyPath:varName]; return val; return nil; } -(NSString *)description { return [NSString stringWithFormat:@"Current Variables: %@", _variablesDict]; } @end 

Ecco la risposta accettata come categoria:

 @implementation NSURL(Parsing) - (NSString *)valueForParameterWithKey:(NSString *)key { for (NSString *var in self.parameterKeys) { if (var.length > key.length+1 && [[var substringWithRange:NSMakeRange(0, key.length+1)] isEqualToString:[key stringByAppendingString:@"="]]) { NSString *varValue = [var substringFromIndex:key.length+1]; return varValue; } } return nil; } - (NSArray *)parameterKeys { NSScanner *scanner = [NSScanner scannerWithString:self.absoluteString]; [scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@"&?"]]; NSString *tempString; NSMutableArray *vars = [NSMutableArray new]; [scanner scanUpToString:@"?" intoString:nil]; while ([scanner scanUpToString:@"&" intoString:&tempString]) { [vars addObject:tempString.copy]; } return vars; } @end 

Tutte le risposte attuali sono specifiche o inutilmente sprecate. Perché creare un dizionario se si desidera solo un valore?

Ecco una risposta semplice che supporta tutte le versioni di iOS:

 - (NSString *)getQueryParam:(NSString *)name fromURL:(NSURL *)url { if (url) { NSArray *urlComponents = [url.query componentsSeparatedByString:@"&"]; for (NSString *keyValuePair in urlComponents) { NSArray *pairComponents = [keyValuePair componentsSeparatedByString:@"="]; NSString *key = [[pairComponents firstObject] stringByRemovingPercentEncoding]; if ([key isEqualToString:name]) { return [[pairComponents lastObject] stringByRemovingPercentEncoding]; } } } return nil; } 

Il più veloce è:

 NSString* x = [url valueForQueryParameterKey:@"x"];