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¶mB=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:
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"];