Сделайте NSURL с закодированным плюсом (% 2B) - PullRequest
11 голосов
/ 22 мая 2009

Мне нужно передать метку времени со смещением часового пояса в запросе GET, например,

2009-05-04T11: 22: 00 + 01: 00

Это похоже на два аргумента "2009-05-04T11: 22: 00" и "01:00" для принимающего скрипта PHP (над которым я не могу управлять).

NSURL не кодирует знаки плюс, но если я сделаю NSURL, используя строку

2009-05-04T11: 22: 00% 2B01: 00

URL, который я получаю, содержит:

2009-05-04T11: 22: 00% 252B01: 00

Есть идеи, как мне сохранить свой закодированный знак плюс или просто запретить NSURL что-либо кодировать?

Ответы [ 7 ]

13 голосов
/ 16 февраля 2010

Для меня работало преобразование 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"];
3 голосов
/ 18 июня 2013

Строка должна быть в кодировке 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));
}
2 голосов
/ 23 мая 2009

Я подумал, что я могу также предоставить мой обходной путь в качестве ответа, поскольку я не думаю, что есть хорошее решение исходной проблемы.

Знак плюс (+) полностью действителен в URL, поэтому я решил преобразовать время в GMT и удалить смещение часового пояса / летнее время из строки. Я оставлю это в качестве упражнения для читателя, чтобы определить значение secondsFromGMT ниже, поскольку, в моем случае, оно всегда одинаково, потому что меня интересуют только метки времени, генерируемые веб-сервером.

NSString *gmtWhen = [[self descriptionWithCalendarFormat:nil
                           timeZone:[NSTimeZone
                           timeZoneForSecondsFromGMT:secondsFromGMT
                     ] locale:nil] stringByReplacingOccurrencesOfString:@" +0000" withString:@""];
2 голосов
/ 22 мая 2009

Используйте NSString 'stringByAddingPercentEscapesUsingEncoding: метод для текста, который вы хотите включить в качестве аргумента.

Как следует из названия, метод преобразует возвращаемую автоматически освобожденную строку, содержащую безопасную для URL версию получателя.

0 голосов
/ 06 ноября 2016

Решение при использовании URLComponents (Swift 3):

var params = ["email": "user+ios-default@example.com", "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=user+ios-default@example.com

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%2Bios-default@example.com
0 голосов
/ 29 июня 2015

Чтобы получить кодированный плюс (% 2B) (работает со всеми символами), используйте 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 = @":/?&=;+!@#$()',*";

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]];
0 голосов
/ 01 октября 2014

закодируйте вашу строку, используя код ниже

NSString * result = (NSString *) CFURLCreateStringByAddingPercentEscapes (NULL, (CFStringRef) самостоятельно, NULL, (CFStringRef) @ "+", kCFStringEncodingUTF8);

это закодирует + вашу строку, что предотвратит замену + на% 2b при публикации данных в методе post

...