Objective-C:如何将查询参数添加到NSURL?

时间:2011-06-10 17:00:31

标签: objective-c query-string nsurl

假设我有NSURL?无论它是否已有空查询字符串,如何将一个或多个参数添加到query的{​​{1}}?即,有没有人知道这个功能的实现?

NSURL

这样它就满足了这个- (NSURL *)URLByAppendingQueryString:(NSString *)queryString 文件:

NSURL+AdditionsSpec.h

8 个答案:

答案 0 :(得分:71)

iOS 7 以来,您可以使用非常简单易用的 NSURLComponents 。看看这些例子:

示例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);

示例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
}

示例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]]];

但你可以用NSURLComponents做很多其他的事情来看看Apple文档或这个链接上的NSURLComponents类引用:http://nshipster.com/nsurl/

答案 1 :(得分:41)

这是一个通过您的规范的实现:

@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

这是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

答案 2 :(得分:23)

iOS8 +现代方式

添加(或替换'ref'值,如果存在)ref = impm到min60.com上的url

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

答案 3 :(得分:8)

对于那些不想在使用NSURL构建NSURLComponents时编写样板代码的人来说,这是一篇友好的帖子。
从iOS8开始,我们NSURLQueryItem可以帮助您快速构建网址请求。

我写了一个方便的类别来简化工作,你可以抓住这里:URLQueryBuilder
以下是使用它是多么容易的例子:

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

答案 4 :(得分:5)

如果您使用的是RestKit,则会提供additions to NSString。其中之一是:

- (NSString *)stringByAppendingQueryParameters:(NSDictionary *)queryParameters

所以你可以这样做:

NSDictionary *shopParams = [NSDictionary dictionaryWithKeysAndObjects:
                                @"limit",@"20", 
                                @"location",@"latitude,longitude",
                                nil];
NSString *pathWithQuery = [@"/api/v1/shops.json" stringByAppendingQueryParameters:shopParams]

答案 5 :(得分:5)

我有NSURLComponents的扩展程序,用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
    }

}

使用,

let components = NSURLComponents(string: urlString)!
components.appendQueryItem(name: "key", value: "value")

答案 6 :(得分:1)

上面的答案提到了NSURLComponents,它是处理URL的好方法。

我的回答如下:

使用NSURL创建一个类别,例如NSURL + Additions.h。然后,添加以下方法并实现它。

- (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];
}

答案 7 :(得分:0)

NSURL不可变,因此您无法直接基于NSURL实现此功能。相反,您必须获取URL的字符串表示形式,将参数附加到该表示形式,然后创建新的NSURL。

这听起来不是一个好的解决方案。除非有充分的理由,否则最好在最后一刻使用字符串,只有在完全形成请求时才创建NSURL。