web-dev-qa-db-fra.com

Objective-C: comment ajouter un paramètre de requête à NSURL?

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
56
ma11hew28

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
43
ma11hew28

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/

72
Salmo

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];
}
23
Peter Lapisu

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
8
Soberman

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]
5
drewish

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")
5
samwize

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];
}
1
wangpeng

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.

0
Rog