Disons que j'ai un NSURL
? Qu'il ait ou non déjà une chaîne de requête vide, comment ajouter un ou plusieurs paramètres au query
du NSURL
? C'est-à-dire, quelqu'un connaît-il une implémentation de cette fonction?
- (NSURL *)URLByAppendingQueryString:(NSString *)queryString
Pour qu'il satisfasse à cette NSURL+AdditionsSpec.h
fichier:
#import "NSURL+Additions.h"
#import "Kiwi.h"
SPEC_BEGIN(NSURL_AdditionsSpec)
describe(@"NSURL+Additions", ^{
__block NSURL *aURL;
beforeEach(^{
aURL = [[NSURL alloc] initWithString:@"http://www.example.com"];
aURLWithQuery = [[NSURL alloc] initWithString:@"http://www.example.com?key=value"];
});
afterEach(^{
[aURL release];
[aURLWithQuery release];
});
describe(@"-URLByAppendingQueryString:", ^{
it(@"adds to plain URL", ^{
[[[[aURL URLByAppendingQueryString:@"key=value&key2=value2"] query] should]
equal:@"key=value&key2=value2"];
});
it(@"appends to the existing query sting", ^{
[[[[aURLWithQuery URLByAppendingQueryString:@"key2=value2&key3=value3"] query] should]
equal:@"key=value&key2=value2&key3=value3"];
});
});
});
SPEC_END
Voici une implémentation qui répond à vos spécifications:
@implementation NSURL (Additions)
- (NSURL *)URLByAppendingQueryString:(NSString *)queryString {
if (![queryString length]) {
return self;
}
NSString *URLString = [[NSString alloc] initWithFormat:@"%@%@%@", [self absoluteString],
[self query] ? @"&" : @"?", queryString];
NSURL *theURL = [NSURL URLWithString:URLString];
[URLString release];
return theURL;
}
@end
Et voici une implémentation pour NSString
:
@implementation NSString (Additions)
- (NSURL *)URLByAppendingQueryString:(NSString *)queryString {
if (![queryString length]) {
return [NSURL URLWithString:self];
}
NSString *URLString = [[NSString alloc] initWithFormat:@"%@%@%@", self,
[self rangeOfString:@"?"].length > 0 ? @"&" : @"?", queryString];
NSURL *theURL = [NSURL URLWithString:URLString];
[URLString release];
return theURL;
}
// Or:
- (NSString *)URLStringByAppendingQueryString:(NSString *)queryString {
if (![queryString length]) {
return self;
}
return [NSString stringWithFormat:@"%@%@%@", self,
[self rangeOfString:@"?"].length > 0 ? @"&" : @"?", queryString];
}
@end
Depuis iOS 7 vous pouvez utiliser NSURLComponents qui est très simple à utiliser. Jetez un œil à ces exemples:
Exemple 1
NSString *urlString = @"https://mail.google.com/mail/u/0/?shva=1#inbox";
NSURLComponents *components = [[NSURLComponents alloc] initWithString:urlString];
NSLog(@"%@ - %@ - %@ - %@", components.scheme, components.Host, components.query, components.fragment);
Exemple 2
NSString *urlString = @"https://mail.google.com/mail/u/0/?shva=1#inbox";
NSURLComponents *components = [[NSURLComponents alloc] initWithString:urlString];
if (components) {
//good URL
} else {
//bad URL
}
Exemple 3
NSURLComponents *components = [NSURLComponents new];
[components setScheme:@"https"];
[components setHost:@"mail.google.com"];
[components setQuery:@"shva=1"];
[components setFragment:@"inbox"];
[components setPath:@"/mail/u/0/"];
[self.webview loadRequest:[[NSURLRequest alloc] initWithURL:[components URL]]];
Mais vous pouvez faire beaucoup d'autres choses avec NSURLComponents jetez un oeil sur la référence de classe NSURLComponents sur Apple ou sur ce lien: http://nshipster.com/nsurl/
La façon moderne iOS8 +
ajout (ou remplacement de la valeur 'ref' s'il existe) ref = impm à l'URL qui se trouve sur min60.com
if ([[url Host] hasSuffix:@"min60.com"]) {
NSURLComponents *components = [[NSURLComponents alloc] initWithURL:url resolvingAgainstBaseURL:NO];
NSURLQueryItem * newQueryItem = [[NSURLQueryItem alloc] initWithName:@"ref" value:@"impm"];
NSMutableArray * newQueryItems = [NSMutableArray arrayWithCapacity:[components.queryItems count] + 1];
for (NSURLQueryItem * qi in components.queryItems) {
if (![qi.name isEqual:newQueryItem.name]) {
[newQueryItems addObject:qi];
}
}
[newQueryItems addObject:newQueryItem];
[components setQueryItems:newQueryItems];
url = [components URL];
}
Juste un article convivial pour ceux qui ne veulent pas écrire de code passe-partout tout en construisant NSURL
avec NSURLComponents
.
Depuis iOS8, nous avons NSURLQueryItem
qui permet de créer rapidement des requêtes d'URL.
J'ai écrit une petite catégorie pratique pour faciliter le travail, que vous pouvez saisir ici: RLQueryBuilder
Voici un exemple de la facilité avec laquelle il est possible de travailler avec:
NSString *baseURL = @"https://google.com/search";
NSDictionary *items = @{
@"q" : @"arsenkin.com",
@"hl" : @"en_US",
@"lr" : @"lang_en"
};
NSURL *URL = [NSURL ars_queryWithString:baseURL queryElements:items];
// https://google.com/search?q=arsenkin.com&hl=en_US&lr=lang_en
Si vous utilisez RestKit, il fournit ajouts à NSString . Dont l'un est:
- (NSString *)stringByAppendingQueryParameters:(NSDictionary *)queryParameters
Vous pourriez donc faire:
NSDictionary *shopParams = [NSDictionary dictionaryWithKeysAndObjects:
@"limit",@"20",
@"location",@"latitude,longitude",
nil];
NSString *pathWithQuery = [@"/api/v1/shops.json" stringByAppendingQueryParameters:shopParams]
J'ai une extension à NSURLComponents
qui ajoute un élément de requête, dans Swift:
extension NSURLComponents {
func appendQueryItem(name name: String, value: String) {
var queryItems: [NSURLQueryItem] = self.queryItems ?? [NSURLQueryItem]()
queryItems.append(NSURLQueryItem(name: name, value: value))
self.queryItems = queryItems
}
}
Utiliser,
let components = NSURLComponents(string: urlString)!
components.appendQueryItem(name: "key", value: "value")
Les réponses ci-dessus mentionnaient les NSURLComponents, c'est une bonne classe pour gérer les URL.
Ma réponse est la suivante:
Créez une catégorie avec NSURL, comme NSURL + Additions.h. Ensuite, ajoutez la méthode suivante et implémentez-la.
- (NSURL *)URLByAppendingQueryParameters:(NSDictionary *)queryParameters
{
if (queryParameters.count == 0) {
return self;
}
NSArray *queryKeys = [queryParameters allKeys];
NSURLComponents *components = [[NSURLComponents alloc] initWithURL:self resolvingAgainstBaseURL:NO];
NSMutableArray * newQueryItems = [NSMutableArray arrayWithCapacity:1];
for (NSURLQueryItem * item in components.queryItems) {
if (![queryKeys containsObject:item.name]) {
[newQueryItems addObject:item];
}
}
for (NSString *key in queryKeys) {
NSURLQueryItem * newQueryItem = [[NSURLQueryItem alloc] initWithName:key value:queryParameters[key]];
[newQueryItems addObject:newQueryItem];
}
[components setQueryItems:newQueryItems];
return [components URL];
}
NSURL n'est pas modifiable, vous ne pouvez donc pas implémenter cette fonctionnalité directement sur la base de NSURL. Au lieu de cela, vous devrez obtenir la représentation sous forme de chaîne de l'URL, y ajouter vos paramètres, puis créer une nouvelle NSURL.
Cela ne semble pas être une bonne solution. À moins qu'il n'y ait une bonne raison, il est préférable de travailler avec des chaînes jusqu'au dernier moment et de créer une NSURL uniquement lorsque votre demande est entièrement formée.