iOS:URL字符串中的“&”符号问题

23

如何在URL中传递字符串“Mr.X&Mr.Y”。

我尝试过这个方法,但它只转换了所有字符,而不是“&”。

[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
6个回答

36
甚至更简单:
@implementation NSString (Escaping)
- (NSString*)stringWithPercentEscape {            
    return [(NSString *) CFURLCreateStringByAddingPercentEscapes(
        NULL, 
        (CFStringRef)[[self mutableCopy] autorelease], 
        NULL, 
        CFSTR("=,!$&'()*+;@?\n\"<>#\t :/"),
        kCFStringEncodingUTF8) autorelease];
}
@end

这里是一个作为ARC符合性内联函数帮助程序的示例:

#if __has_feature(objc_arc)
static inline NSString *hxURLEscape(NSString *v) {
    static CFStringRef _hxURLEscapeChars = CFSTR("=,!$&'()*+;@?\r\n\"<>#\t :/");
    return ((__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(
        NULL, 
        (__bridge CFStringRef)[v mutableCopy], 
        NULL, 
        _hxURLEscapeChars, 
        kCFStringEncodingUTF8));
}
#endif

请查看下面Roger的回答。虽然这个解决方案是一个很好的通用答案,但它并不是一个完整的URL编码实现,截至iOS版本2.2。如果有人对此在后续iOS版本中是否得到修复有任何额外信息,请在此处评论。 - memmons
2
实际上,我认为我们根本不需要复制它,可以用 self 替换 [[self mutableCopy] autorelease]。有关此问题的更多详细信息,请参阅 CFURLCreateStringByAddingPercentEscapes 的文档 http://developer.apple.com/library/mac/#documentation/CoreFoundation/Reference/CFURLRef/Reference/reference.html - Holtwick
这是一篇关于问题的好文章:http://www.mikeabdullah.net/escaping-url-paths-in-cocoa.html - Holtwick

32

-stringByAddingPercentEscapesUsingEncoding:方法并不能对所有字符进行完整的编码,你应该手动使用-replaceOccurrencesOfString:withString:方法添加编码。

以下是一个完整的列表(与Gamecat给出的列表相同),最初建议在https://devforums.apple.com/message/15674#15674上。正如Nick所指出的那样,这个方法很费资源,因此在考虑转义的实际需求时不要简单地包含完整的列表。

NSMutableString *escaped = [actionString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];   
[escaped replaceOccurrencesOfString:@"$" withString:@"%24" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@"&" withString:@"%26" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@"+" withString:@"%2B" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@"," withString:@"%2C" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@"/" withString:@"%2F" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@":" withString:@"%3A" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@";" withString:@"%3B" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@"=" withString:@"%3D" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@"?" withString:@"%3F" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@"@" withString:@"%40" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@" " withString:@"%20" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@"\t" withString:@"%09" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@"#" withString:@"%23" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@"<" withString:@"%3C" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@">" withString:@"%3E" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@"\"" withString:@"%22" options:NSCaseInsensitiveSearch range:wholeString];
[escaped replaceOccurrencesOfString:@"\n" withString:@"%0A" options:NSCaseInsensitiveSearch range:wholeString];

这段代码肯定会对你的URL进行哈希处理。

8
我认为正确的代码应该更像是: NSMutableString *escaped = [NSMutableString stringWithString:[actionString ...]]; 并且使用 NSMakeRange(0, [escaped length]),而不是使用 wholeString。 - kolinko
1
这很昂贵,CFURLCreateStringByAddingPercentEscapes() 更好。 - Nick Toumpelis
CFURLCreateStringByAddingPercentEscapes是否与stringByAddingPercentEscapesUsingEncoding存在相同的问题? - Rog

5

使用%26作为URL转义。

其他转义:

$  %24
&  %26
+  %2B
,  %2C
/  %2F
:  %3A
;  %3B
=  %3D
?  %3F
@  %40

如果我执行以下操作,我就对了吗?[statusTextField.text stringByReplacingOccurrencesOfString:@"&" withString:@"%26"]然后在我的服务器端,我将%26替换为&并存储在数据库中。 - Oceandrive

0

CFURLCreateStringByAddingPercentEscapes已经被弃用(自iOS9起),那么我们可以将URLQueryAllowedCharacterSet修改一下,去掉保留字符,从而允许它们被相对高效地百分比编码。

- (NSString *)URLQueryValueEncodedString:(NSString *)string {
    static NSMutableCharacterSet *_allowedCharacterSet = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSString *reservedCharacters = @"=,!$&'()*+;@?\r\n\"<>#\t :/[]%";
        _allowedCharacterSet = [NSCharacterSet URLQueryAllowedCharacterSet].mutableCopy;
        [_allowedCharacterSet removeCharactersInString:reservedCharacters];
    });

    return [string stringByAddingPercentEncodingWithAllowedCharacters:_allowedCharacterSet];
}

0

stringByAddingPercentEscapesUsingEncoding 也无法正确处理 +

这里有一个更简单的解决方案:

[[[urlString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding] stringByReplacingOccurrencesOfString:@"&" withString:@"%26"] stringByReplacingOccurrencesOfString:@"+" withString:@"%2b"];

-2
在URL中,&符号是一个受保护的关键字,表示包含查询字符串变量。您不能将其作为值本身的一部分放入其中。您需要将其更改为其他内容。
以下是同一问题在StackOverflow上提出的链接:ASP.Net URLEncode Ampersand for use in Query String

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接