Создайте NSURL с кодированным плюсом (% 2B)
Мне нужно передать временную метку с смещением часового пояса в запросе GET, например,
2009-05-04T11: 22: 00 + 01: 00
Это выглядит как два аргумента "2009-05-04T11: 22: 00" и "01:00" для получающего PHP script (над которым я не контролирую).
NSURL не кодирует плюсовые знаки, но если я создаю NSURL, используя строку
2009-05-04T11: 22: 00% 2B01: 00
URL-адрес, в который я заканчиваюсь, содержит:
2009-05-04T11: 22: 00% 252B01: 00
Любые идеи, как я могу сохранить свой кодированный знак плюса или просто запретить NSURL кодировать что-нибудь?
Ответы
Ответ 1
Что сработало для меня, это преобразование UTF8, а затем заменив знак + на% 2B:
NSString *urlString =
[NSString stringWithFormat:@"%@/iphone/push/create?pn[token]=%@&pn[send_at]=%@",
kHTTPURL, appDelegate.deviceAPNToken, [dateTimeToUse description]];
urlString =
[[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"];
Ответ 2
Строка должна быть закодирована в URL.
Вот категория для NSString, которая поможет:
NSString + Additions.h
@interface NSString (Additions)
- (NSString *)stringByURLEncoding;
NSString + Additions.m
#import "NSString+Additions.h"
@implementation NSString (Additions)
- (NSString *)stringByURLEncoding {
return (__bridge NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,
NULL,
(CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
}
Ответ 3
Используйте текст NSString
stringByAddingPercentEscapesUsingEncoding:
для текста, который вы хотите включить в качестве аргумента.
Как следует из названия, метод будет преобразовывать возвращаемую автоматически выпущенную строку, содержащую безопасную версию получателя.
Ответ 4
Мысль о том, что я могу предоставить свое обходное решение как ответ, поскольку я не думаю, что там есть хорошее решение исходной проблемы.
Знак плюса (+) полностью действителен в URL-адресе, поэтому моим решением было преобразовать время в GMT и удалить смещение часового пояса /DST из строки. Я оставлю это как упражнение для читателя, чтобы определить значение secondsFromGMT ниже, поскольку в моем случае это всегда одно и то же, потому что меня интересуют только временные метки, созданные веб-сервером.
NSString *gmtWhen = [[self descriptionWithCalendarFormat:nil
timeZone:[NSTimeZone
timeZoneForSecondsFromGMT:secondsFromGMT
] locale:nil] stringByReplacingOccurrencesOfString:@" +0000" withString:@""];
Ответ 5
закодируйте строку, используя приведенный ниже код
NSString * result = (NSString *) CFURLCreateStringByAddingPercentEscapes (NULL,
(CFStringRef) самостоятельно, NULL, (CFStringRef) @ "+", kCFStringEncodingUTF8);
это будет кодировать + вашу строку, которая предотвратит замену + на% 2b при публикации данных в методе post
Ответ 6
Чтобы получить кодированный плюс (% 2B) (он работает со всеми charcters), используйте CFURLCreateStringByAddingPercentEscapes
как
/**
get parameterized url from url and query parameters.
*/
+(NSString *)getParameterizedUrl:(NSString *)url withParameters:(NSDictionary *)queryDictionary
{
NSMutableArray *mutablePairs = [NSMutableArray array];
for (NSString *key in queryDictionary) {
[mutablePairs addObject:[NSString stringWithFormat:@"%@=%@", CTPercentEscapedQueryStringKeyFromStringWithEncoding(key, NSUTF8StringEncoding), CTPercentEscapedQueryStringValueFromStringWithEncoding(queryDictionary[key], NSUTF8StringEncoding)]];
}
return [[NSString alloc]initWithFormat:@"%@?%@",url,[mutablePairs componentsJoinedByString:@"&"]];
}
static NSString * const kCharactersToBeEscapedInQueryString = @":/?&=;[email protected]#$()',*";
static NSString * CTPercentEscapedQueryStringKeyFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
static NSString * const kCharactersToLeaveUnescapedInQueryStringPairKey = @"[].";
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kCharactersToLeaveUnescapedInQueryStringPairKey, (__bridge CFStringRef)kCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding));
}
static NSString * CTPercentEscapedQueryStringValueFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, (__bridge CFStringRef)kCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding));
}
И используйте в своем коде как
NSMutableDictionary *params = [[NSMutableDictionary alloc]init];
[params setObject:@"2009-05-04T11:22:00+01:00" forKey:@"timestamp"];
NSString *urlString = [self getParameterizedUrl:@"http://www.example.com" withParameters:params];
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
Ответ 7
Решение при использовании URLComponents (Swift 3):
var params = ["email": "[email protected]", "name": "John Brown"]
var components = URLComponents(string: "http://www.example.com")!
components.path = "/login"
components.queryItems = params.map { URLQueryItem(name: $0, value: $1) }
let url_NoFix = components.url!
// http://www.example.com/login?name=John%20Brown&[email protected]
let cs = CharacterSet(charactersIn: "+").inverted
let q = components.percentEncodedQuery?.addingPercentEncoding(withAllowedCharacters: cs)
components.percentEncodedQuery = q
let url_Fixed = components.url!
// http://www.example.com/login?name=John%20Brown&email=user%[email protected]