2009-12-27 5 views
12

Esistono oggetti o funzioni standard per analizzare i componenti di un NSURL? Chiaramente potrei scriverne uno, ma perché reinventare la ruota?Percorso NSURL di analisi e query (iphoneOS)

[NSURL path] restituirà un NSString come "argX=x&argY=y&argZ=z" Cosa avrei preferito tornare è un dizionario popolato con {@"argX" => @"x", @"argY" => @"y", @"argZ" = @"z"}

Per il percorso, che restituisce una stringa come "/ PARTA/PARTE B/PARTC", avrei preferito arrivare un allineamento con la struttura {[0] => @"partA", [1] => @"partB", [2] => @"partC"}

mi rendo conto che questo è un grazioso specifica chiedere, ma sembra qualcosa di un sacco di gente vorrebbe ...

EDIT - questo è per iPhoneOS! A quanto pare NSURL ha diverse funzioni su Mac OS

+0

Buona domanda. Vuoi dire: se l'URL è "/ partA/partB/partC", vuoi "0 => partA, 1 => partB, 2 => partC". Se l'URL è "/ foo? PartA = A & partB = B" vuoi "partA => A, partB => B". Cosa succede se l'URL è "/ partA/partB/partC? Foo = bar & ooga = booga"? In un esempio, le informazioni importanti necessarie per identificare l'entità in questione vengono passate in una stringa di query ... nell'altro esempio, le informazioni di identificazione vengono passate in stile di riposo nel percorso stesso. –

+0

Voglio dire, voglio analizzare il percorso e la query separatamente. Non dovrebbe essere una funzione che combina questi due compiti. Vedere il codice che ho postato di seguito per chiarimenti. Se qualcuno risponde con un'implementazione esistente, sarò felice di accettarlo ancora. – DougW

+0

Una cosa da tenere a mente è che questa è una stringa di query perfettamente valida: "x = 1 & x = 0 & x = pippo", quindi un NSDictionary potrebbe non essere la migliore rappresentazione (a meno che non si utilizzino gli array come valori). – n8gray

risposta

9

Si potrebbe voler vedere pathComponents che restituisce una matrice dei componenti dell'URL. Più informazioni here.

+0

Non credo sia disponibile nella versione per iPhone dell'SDK. Avrei dovuto chiarire che sto lavorando su iOS. – DougW

+2

[NSString pathComponents] è disponibile in entrambe le API Cocoa e Cocoa Touch. Sull'iPhone, è possibile imitare [NSURL pathComponents] di OS X 10.6 con [[Percorso NSURL] pathComponents]. –

+0

Ah perfetto, questo è quello che stavo cercando, almeno per la porzione di percorso! – DougW

2

Se si decide di scrivere una (io non sono sicuro che ci sono metodi esistenti di ottenere i componenti desiderati), si potrebbe desiderare di utilizzare NSString di componentsSeparatedByString.

+0

Grazie, mi ha salvato un po 'del lavoro! – DougW

12

OK, ho avuto Antsy e ho scritto una soluzione per estendere NSString attraverso le Categorie. Non ho ancora provato questo, ma se vuoi usarlo, provaci.

@interface NSString (ParseCategory) 
- (NSMutableDictionary *)explodeToDictionaryInnerGlue:(NSString *)innerGlue outterGlue:(NSString *)outterGlue; 
@end 

@implementation NSString (ParseCategory) 

- (NSMutableDictionary *)explodeToDictionaryInnerGlue:(NSString *)innerGlue outterGlue:(NSString *)outterGlue { 
    // Explode based on outter glue 
    NSArray *firstExplode = [self componentsSeparatedByString:outterGlue]; 
    NSArray *secondExplode; 

    // Explode based on inner glue 
    NSInteger count = [firstExplode count]; 
    NSMutableDictionary *returnDictionary = [NSMutableDictionary dictionaryWithCapacity:count]; 
    for (NSInteger i = 0; i < count; i++) { 
     secondExplode = [(NSString *)[firstExplode objectAtIndex:i] componentsSeparatedByString:innerGlue]; 
     if ([secondExplode count] == 2) { 
      [returnDictionary setObject:[secondExplode objectAtIndex:1] forKey:[secondExplode objectAtIndex:0]]; 
     } 
    } 

    return returnDictionary; 
} 

@end 

Si chiama così:

NSMutableDictionary *parsedQuery = [[myNSURL query] explodeToDictionaryInnerGlue:@"=" [email protected]"&"] 

Per l'analisi del porzione di percorso del NSURL (cioè @ "/ PARTA/PARTE B/PARTC"), basta chiamare questo:

NSArray *parsedPath = [[nyNSURL path] componentsSeperatedByString:@"/"]; 

Si noti che parsedPath [0] sarà una stringa vuota a causa del comando /!

EDIT - Ecco un'estensione di categoria per NSURL per il vostro piacere di utilizzo. Strisce l'iniziale "/" in modo da non avere un indice 0 vuoto.

@implementation NSURL (ParseCategory) 

- (NSArray *)pathArray { 
    // Create a character set for the slash character 
    NSRange slashRange; 
    slashRange.location = (unsigned int)'/'; 
    slashRange.length = 1; 
    NSCharacterSet *slashSet = [NSCharacterSet characterSetWithRange:slashRange]; 

    // Get path with leading (and trailing) slashes removed 
    NSString *path = [[self path] stringByTrimmingCharactersInSet:slashSet]; 

    return [path componentsSeparatedByCharactersInSet:slashSet]; 
} 

- (NSDictionary *)queryDictionary { 
    NSDictionary *returnDictionary = [[[[self query] explodeToDictionaryInnerGlue:@"=" outterGlue:@"&"] copy] autorelease]; 
    return returnDictionary; 
} 

@end 
+0

Non so perché qualcuno abbia votato questo ... mi insegnerà a condividere il codice, immagino? Non mi dispiacerebbe davvero se avessi lasciato un commento, ma presumo che tu sia un troll casuale. Ciao troll. – DougW

+4

Grazie, per me va bene.Tieni presente che potrebbe essere necessario decodificare l'URL anche i singoli valori della stringa di query. Sto usando il seguente codice per questo, prima di occuparmi di percent-escape, quindi di sostituire "+" con spazio, che il primo purtroppo non funziona: [[value stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding] stringByReplacingOccurrencesOfString: @ "+ "withString: @" "] –

+0

Molto benvenuto. E sì, ho lasciato le questioni di codifica/decodifica di queste funzioni. – DougW

5

Heres quello che uso per analizzare la stringa di query

// Parse the individual parameters 
// parameters = @"hello=world&foo=bar"; 
NSMutableDictionary *dictParameters = [[NSMutableDictionary alloc] init]; 
NSArray *arrParameters = [parameters componentsSeparatedByString:@"&"]; 
for (int i = 0; i < [arrParameters count]; i++) { 
    NSArray *arrKeyValue = [[arrParameters objectAtIndex:i] componentsSeparatedByString:@"="]; 
    if ([arrKeyValue count] >= 2) { 
     NSMutableString *strKey = [NSMutableString stringWithCapacity:0]; 
     [strKey setString:[[[arrKeyValue objectAtIndex:0] lowercaseString] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]]; 
     NSMutableString *strValue = [NSMutableString stringWithCapacity:0]; 
     [strValue setString:[[[arrKeyValue objectAtIndex:1] stringByReplacingOccurrencesOfString:@"+" withString:@" "] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]]; 
     if (strKey.length > 0) [dictParameters setObject:strValue forKey:strKey]; 
    } 
} 
NSLog(@"Parameters: %@", dictParameters); 
2

Introdotto in iOS 8 e OS X 10.10 è NSURLQueryItem, che può essere utilizzata per creare query. Dalla documentazione sul NSURLQueryItem:

Un NSURLQueryItem oggetto rappresenta una singola coppia nome/valore per un elemento nella parte interrogazione di un URL. Si utilizzano gli elementi di query con la proprietà queryItems di un oggetto NSURLComponents.

È possibile recuperare gli elementi di query da un URL creando prima NSURLComponents:

NSURL *url = [NSURL URLWithString:@"http://stackoverflow.com?q=ios&count=10"]; 
NSURLComponents *components = [NSURLComponents componentsWithURL:url 
               resolvingAgainstBaseURL:YES]; 
for (NSURLQueryItem *item in components.queryItems) { 
    NSLog(@"name: %@, value: %@", item.name, item.value); 
} 
// name: q, value: ios 
// name: count, value: 10 

noti che tornano rapporto qualità--queryItems è un array, non un dizionario. Questo perché il seguente è un URL valido. Notare i due "tasti" identici, foo.

http://google.com?foo=bar&foo=baz

per creare un URL tramite elementi di query, utilizzare l'inizializzatore designato queryItemWithName:value: e poi aggiungerli al NSURLComponents per generare un NSURL. Ad esempio:

NSString *urlString = @"http://stackoverflow.com"; 
NSURLComponents *components = [NSURLComponents componentsWithString:urlString]; 
NSURLQueryItem *search = [NSURLQueryItem queryItemWithName:@"q" value:@"ios"]; 
NSURLQueryItem *count = [NSURLQueryItem queryItemWithName:@"count" value:@"10"]; 
components.queryItems = @[ search, count ]; 
NSURL *url = components.URL; // http://stackoverflow.com?q=ios&count=10 

Si noti che il punto interrogativo e la e commerciale vengono gestiti automaticamente. Creazione di un NSURL da un dizionario dei parametri è semplice come:

NSDictionary *queryDictionary = @{ @"q": @"ios", @"count": @"10" }; 
NSMutableArray *queryItems = [NSMutableArray array]; 
for (NSString *key in queryDictionary) { 
    NSURLQueryItem *item = [NSURLQueryItem queryItemWithName:key 
                 value:queryDictionary[key]]; 
    [queryItems addObject:item]; 
} 
components.queryItems = queryItems; 

Ho anche scritto un post sul blog con più dettagli, Building NSURLs with NSURLQueryItems.

+0

Cool! Solo una nota per gli sviluppatori: se utilizzi parametri GET duplicati, ti trovi in ​​un mondo di dolore. Non ci sono specifiche definite su come gestirle, e diverse lingue/piattaforme compongono le proprie regole. Vedi http://stackoverflow.com/questions/1746507/authoritative-position-of-duplicate-http-get-query-keys – DougW