使用编码加号 (%2B) 创建 NSURL

发布于 2024-07-22 06:14:25 字数 414 浏览 4 评论 0原文

我需要在 GET 请求中传递带有时区偏移量的时间戳,例如,

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

这看起来像是接收 PHP 脚本的两个参数“2009-05-04T11:22:00”和“01:00”(我无法控制) 。

NSURL 不编码加号,但如果我使用字符串创建 NSURL

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

我最终得到的网址包含:

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

有什么想法可以保留我编码的加号或只是简单地阻止 NSURL 编码任何内容吗?

I need to pass a timestamp with a timezone offset in a GET request, e.g.,

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

This looks like a two arguments "2009-05-04T11:22:00" and "01:00" to the receiving PHP script (over which I've no control).

NSURL doesn't encode plus signs, but if I make an NSURL using the string

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

the url I end up with contains:

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

Any ideas how I can preserve my encoded plus sign or just plain prevent NSURL from encoding anything?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

睫毛上残留的泪 2024-07-29 06:14:25

对我有用的是进行 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"];

What worked for me was doing the UTF8 conversion, then replacing the + sign with %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"];
昇り龍 2024-07-29 06:14:25

该字符串应该是 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));
}

The string should be URL encoded.

Here is a category for NSString that will help:

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));
}
贩梦商人 2024-07-29 06:14:25

对要作为参数包含的文本使用 NSStringstringByAddingPercentEscapesUsingEncoding: 方法。

顾名思义,该方法将转换返回一个自动释放的字符串,其中包含接收者的 url 安全版本。

Use NSString's stringByAddingPercentEscapesUsingEncoding: method on the text you want to include as an argument.

As its name implies, the method will convert return an auto-released string containing an url-safe version of the receiver.

青瓷清茶倾城歌 2024-07-29 06:14:25

我想我也可以提供我的解决方法作为答案,因为我认为原始问题没有一个好的解决方案。

加号 (+) 在 URL 中完全有效,因此我的解决方案是将时间转换为 GMT 并从字符串中删除时区/DST 偏移量。 我将把它作为练习留给读者来确定下面的 secondsFromGMT 的值,在我的例子中,它总是相同的,因为我只对网络服务器生成的时间戳感兴趣。

NSString *gmtWhen = [[self descriptionWithCalendarFormat:nil
                           timeZone:[NSTimeZone
                           timeZoneForSecondsFromGMT:secondsFromGMT
                     ] locale:nil] stringByReplacingOccurrencesOfString:@" +0000" withString:@""];

Thought I may as well provide my workaround as an answer, as I don't think there's a good solution to the original problem.

The plus sign (+) is completely valid in a URL, so my solution was to convert the time to GMT and remove the timezone/DST offset from the string. I'll leave it as an exercise for the reader to determine the value of secondsFromGMT below as, in my case, it's always the same because I'm only interested in timestamps generated by a web server.

NSString *gmtWhen = [[self descriptionWithCalendarFormat:nil
                           timeZone:[NSTimeZone
                           timeZoneForSecondsFromGMT:secondsFromGMT
                     ] locale:nil] stringByReplacingOccurrencesOfString:@" +0000" withString:@""];
孤寂小茶 2024-07-29 06:14:25

使用 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]

Solution when using 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]
温馨耳语 2024-07-29 06:14:25

使用以下代码对字符串进行编码

NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,NULL,(CFStringRef)@"+",kCFStringEncodingUTF8);

这将对字符串的 + 进行编码,从而防止在 post 方法中发布数据时将 + 替换为 %2b

encode you string by using below code

NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,NULL,(CFStringRef)@"+",kCFStringEncodingUTF8);

this will encode + of you string which will prevent replacement of + by %2b while posting data in post method

梦开始←不甜 2024-07-29 06:14:25

要获得编码加号 (%2B)(它适用于所有字符),请使用 CFURLCreateStringByAddingPercentEscapes as

/**
 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));
}

并在代码中使用 as

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]];

To get encoded plus (%2B) (It works with all charcters) use CFURLCreateStringByAddingPercentEscapes as

/**
 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));
}

And use in your code as

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]];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文