J'ai un NSURL:NSURL tirer une valeur unique pour une clé dans une chaîne de paramètres
serverCall x = a & y = b & z = c
Quel est le moyen le plus rapide et le plus efficace pour obtenir la valeur de y?
Merci
J'ai un NSURL:NSURL tirer une valeur unique pour une clé dans une chaîne de paramètres
serverCall x = a & y = b & z = c
Quel est le moyen le plus rapide et le plus efficace pour obtenir la valeur de y?
Merci
MISE À JOUR:
Depuis 2010, lorsque cela a été écrit, il semble Apple a publié un ensemble d'outils à cette fin. S'il vous plaît voir les réponses ci-dessous pour ceux.
Old-School Solution:
Eh bien, je sais que vous avez dit « la plus rapide » mais après avoir commencé à faire un test avec NSScanner
je ne pouvais pas arrêter. Et même si ce n'est pas le chemin le plus court, il est très pratique si vous prévoyez d'utiliser cette fonctionnalité. J'ai créé une classe URLParser
qui obtient ces vars en utilisant un NSScanner
. L'utilisation est simple:
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
Et la classe qui fait cela est la suivante (* fichiers source au bas du poste):
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
* Si vous n'aimez pas copier et coller vous pouvez simplement télécharger les fichiers source - J'ai fait un blog rapide sur ce here.
Je recommande regarder getResourceValue:forKey:error:
. Le paramètre forKey
sera y
, je crois.
hein, je viens juste essayé et cela n'a pas fonctionné ... –
Cela semble fonctionner uniquement sur OSX, et non iPhone. – Dave
Ce n'est pas ce que signifie "ressource" dans ce cas. Les propriétés des ressources ont à voir avec les fichiers. Reportez-vous à «Clés de ressources du système de fichiers commun» dans les documents NSURL pour obtenir des exemples des types de propriétés que cette routine retourne. –
Je suis sûr que vous devez l'analyser vous-même. Cependant, il est pas trop mal:
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"]);
Vous devriez utiliser 'NSUTF8StringEncoding' plutôt que' NSASCIIStringEncoding' sauf si vous détestez les non-anglophones. –
Il a raison, vous savez Dave, bien qu'il s'agisse d'une question d'encodage, le système d'URL en question a décidé d'utiliser. Pour presque tout ce qui existe, c'est UTF-8, heureusement –
Merci de m'avoir gardé il y a 3 ans honnête :) –
est Quickest:
NSString* x = [url valueForQueryParameterKey:@"x"];
Vous pouvez utiliser Google Toolbox for Mac. Il ajoute une fonction à NSString pour convertir la chaîne de requête en dictionnaire.
http://code.google.com/p/google-toolbox-for-mac/
Il fonctionne comme un charme
NSDictionary * d = [NSDictionary gtm_dictionaryWithHttpArgumentsString:[[request URL] query]];
Je l'ai fait en utilisant une méthode de catégorie basée sur la solution @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
+1: Je suis d'accord que cela est mieux adapté pour un 'NSDictionary' que 'NSArray'. Cependant, si vous allez utiliser cette fonction, assurez-vous que vous assignez cette valeur à un ivar ... ie 'NSDictionary * paramsDict = [myURL dictionaryValue]' ... vous ne voulez pas construire ce dictionnaire encore et encore pour obtenir la valeur de chaque paramètre ...; P –
j'ai écrit une catégorie simple d'étendre NSString/NSURL qui vous permet d'extraire les paramètres de requête d'URL individuellement ou en tant que dictionnaire de paires clé/valeur:
Vous pouvez le faire facilement:
- (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;
}
Il retourne Dictionnaire semblable: Key = valeur
Cela ne fonctionne pas. les clés et les valeurs sont toutes mélangées. – slevytam
Je me sers de cette catégorie: https://github.com/carlj/NSURL-Parameters.
Il est petit et facile à utiliser:
#import "NSURL+Parameters.h"
...
NSURL *url = [NSURL URLWithString:@"http://foo.bar.com?paramA=valueA¶mB=valueB"];
NSString *paramA = url[@"paramA"];
NSString *paramB = url[@"paramB"];
simple, propre, efficace. la meilleure réponse je pense. THX. – neywen
wow, exactement ce dont j'avais besoin, si simple à utiliser – morksinaanab
Je modifié le code de Dimitris légèrement pour une meilleure gestion et l'efficacité mémoire. En outre, cela fonctionne dans 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
Swift vous pouvez utiliser NSURLComponents pour analyser la chaîne de requête d'un NSURL dans un [ANYOBJECT].
Vous pouvez ensuite créer un dictionnaire à partir de celui-ci (ou accéder directement aux éléments) pour obtenir les paires clé/valeur. À titre d'exemple ce que je suis en utilisant pour analyser une variable NSURL url:
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"])
Cela devrait être la réponse acceptée maintenant: l'un actuellement accepté a été remplacé. Cette approche n'est pas seulement pour Swift; Objective-C peut aussi utiliser NSURLComponents. Il est disponible à partir d'iOS 7: http://nshipster.com/nsurl/ – SeanR
Tant de parseurs url personnalisé ici, rappelez-vous NSURLComponents est votre ami!
Voici un exemple où je tire un paramètre codé url pour "page"
Swift
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];
}
" Pourquoi réinventer la roue ! " - Quelqu'un intelligent
En fait, je ne comprends pas pourquoi cette réponse n'est pas marquée comme corrigée. Merci @anders. –
@ AlexKrzyżanowski, en retard au jeu: P – anders
Un peu plus compact: let pageNumber: Int? = Int (NSURLComponents (string: myURL.absoluteString ?? "")?. QueryItems? .filter {$ 0.name == "page"} .première? .value ??"NaN") –
Voici la réponse acceptée comme catégorie:
@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<NSString *> *)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
est ici un Swift 2.0 extension qui fournit un accès simple aux paramètres:
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
}
}
}
Exemple d'utilisation:
let url = NSURL(string: "http://google.com?test=dolphins")
if let testParam = url.params["test"] {
print("testParam: \(testParam)")
}
Super extension, bien écrite, simple et fonctionne très bien! – Unome
Toutes les réponses actuelles sont inutilement ou version spécifique du gaspillage. Pourquoi créer un dictionnaire si vous ne voulez qu'une seule valeur?
Voici une simple, réponse qui prend en charge toutes les versions 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;
}
+1 pour awesomeness! 'NSScanner' est une classe avec laquelle je n'ai pas beaucoup joué, et ça a l'air vraiment intéressant. Le seul commentaire que je dirais est de ne pas appeler la méthode 'getValue ...'. Cela implique (selon la convention) que vous allez renvoyer la valeur via un paramètre out. 'valueForVariable:' serait le nom propre. –
Je n'ai pas joué avec 'NSScanner' avant, donc j'ai pensé que c'était une bonne tâche pour le tester. Quant au nom de la méthode, je ne l'ai pas aimé non plus mais il était 2h00 du matin et je voulais envelopper les choses: P C'est mis à jour. – Dimitris
Merci pour cette classe réutilisable – iOSAppDev