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

Objective-C:如何向NSURL添加查询参数?,objective-c,query-string,nsurl,Objective C,Query String,Nsurl,假设我有一个NSURL?无论它是否已经有空查询字符串,如何向NSURL的query添加一个或多个参数?即,是否有人知道该功能的实现 - (NSURL *)URLByAppendingQueryString:(NSString *)queryString 使其满足此NSURL+AdditionsSpec.h文件: #import "NSURL+Additions.h" #import "Kiwi.h" SPEC_BEGIN(NSURL_AdditionsSpec) describe(@"NS

假设我有一个
NSURL
?无论它是否已经有空查询字符串,如何向
NSURL
query
添加一个或多个参数?即,是否有人知道该功能的实现

- (NSURL *)URLByAppendingQueryString:(NSString *)queryString
使其满足此
NSURL+AdditionsSpec.h
文件:

#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

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


这听起来不是一个好的解决方案。除非有充分的理由,否则最好使用字符串直到最后一刻,并且只有在您有完整格式的请求时才创建NSURL。

以下是通过您的规范的实现:

@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

如果您使用的是RestKit,它会提供。其中之一是:

- (NSString *)stringByAppendingQueryParameters:(NSDictionary *)queryParameters
所以你可以做:

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

由于iOS 7可以使用非常简单的nsurl组件。看看这些例子:

例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做很多其他的事情,看看苹果文档或这个链接上的NSURLComponents类参考:

对于那些不想在用
NSURLComponents
构建
NSURL
时编写样板代码的人来说,这只是一篇友好的帖子
自从iOS8以来,我们有了
NSURLQueryItem
,它可以帮助快速构建URL请求

为了简化工作,我写了一个简单的分类,你可以在这里找到:
下面是使用它的简单性示例:

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

iOS8+现代方式

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


我对添加查询项的
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")

上面的答案提到了nsurl组件,它是一个处理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];
}

回答很好,但为了完全安全,在构建URLString时应该使用[queryString StringByAddingPercenteScapesusingEncode:],否则,如果查询字符串尚未“URL友好”(例如,当参数值中有空格时),则结果URL将为零。不适用于带有hashtag(#)的URL,其中,新的查询字符串参数应附加在hashtag之前;不需要。您现在应该真正使用下面Salmo答案中建议的
NSURLComponents
。RKAdditions类别现在不再可用。太棒了!正是我要找的。谢谢你的分类贡献。这一个可能会工作,但它需要添加一个扩展。
- (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];
}