Objective-C: Как добавить параметр запроса в NSURL?
Скажем, у меня есть NSURL
? Независимо от того, имеет ли она уже пустую строку запроса, как добавить один или несколько параметров в query
для NSURL
? 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
Ответы
Ответ 1
Здесь реализована реализация, которая передает ваши спецификации:
@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
Так как 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, взгляните на ссылку класса NSURLComponents на документацию Apple или по этой ссылке: http://nshipster.com/nsurl/
Ответ 3
Современный способ iOS8 +
добавление (или замена значения ref), если существует) ref = impm для url, который находится на 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];
}
Ответ 4
Просто дружественный пост для тех, кто не хочет писать шаблонный код при построении NSURL
с помощью NSURLComponents
.
Поскольку iOS8 имеет NSURLQueryItem
, это помогает быстро ускорить создание запроса URL.
Я написал немного удобную категорию, чтобы облегчить работу, которую вы можете получить здесь: 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
Ответ 5
Если вы используете RestKit, он предоставляет дополнения к NSString. Один из них:
- (NSString *)stringByAppendingQueryParameters:(NSDictionary *)queryParameters
Итак, вы можете сделать:
NSDictionary *shopParams = [NSDictionary dictionaryWithKeysAndObjects:
@"limit",@"20",
@"location",@"latitude,longitude",
nil];
NSString *pathWithQuery = [@"/api/v1/shops.json" stringByAppendingQueryParameters:shopParams]
Ответ 6
У меня есть расширение до 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")
Ответ 7
NSURL не изменен, поэтому вы не можете реализовать эту функцию напрямую на основе NSURL. Вместо этого вам нужно будет получить строковое представление URL-адреса, добавить к нему свои параметры и затем создать новый NSURL.
Это не похоже на хорошее решение. Если нет веской причины, лучше работать со строками до последнего момента и создавать только NSURL, когда у вас есть полностью сформированный запрос.
Ответ 8
В ответах выше упоминаются 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];
}