web-dev-qa-db-ja.com

Objective-C:NSURLにクエリパラメーターを追加する方法

NSURLがあるとしますか?空のクエリ文字列が既にあるかどうかにかかわらず、queryNSURLに1つ以上のパラメーターを追加するにはどうすればよいですか?つまり、この関数の実装を知っている人はいますか?

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

仕様を渡す実装は次のとおりです。

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

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ドキュメンテーションまたはこのリンク: http://nshipster.com/nsurl/

72
Salmo

iOS8 +の最新の方法

min60.comにあるURLにref = impmを追加(または、存在する場合は「ref」値を置換)

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

NSURLNSURLComponentsで構築している間に定型コードを書きたくない人のための友好的な投稿です。
iOS8からは、NSURLQueryItemがあり、URLリクエストの高速化に役立ちます。

作業を簡単にするために少し便利なカテゴリを作成しました。ここで入手できます。 RLQueryBuilder
これを使用するのがいかに簡単かという例を次に示します。

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

RestKitを使用している場合、 NSStringへの追加 が提供されます。その1つは:

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

だからあなたができる:

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

Swiftで、クエリアイテムを追加するNSURLComponentsの拡張機能があります。

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

上記の回答ではNSURLComponentsについて言及しましたが、これはURLを処理するのに適したクラスです。

私の答えは次のとおりです。

NSURL + Additions.hのようなNSURLでカテゴリを作成します。次に、以下のメソッドを追加して実装します。

- (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は変更できないため、NSURLに基​​づいてこの機能を直接実装することはできません。代わりに、URLの文字列表現を取得し、それにパラメーターを追加してから、新しいNSURLを作成する必要があります。

これは良い解決策のようには聞こえません。正当な理由がない限り、最後の瞬間まで文字列を操作し、完全に形成されたリクエストがある場合にのみNSURLを作成することをお勧めします。

0
Rog