iOS NSURL 编码

在 RFC 3986 文档中规定,URL 中只允许包含以下四种:

  1. 英文字母 a-z 以及 A-Z
  2. 数字 0-9
  3. 4个特殊字符:中横线 -、下划线 _、小数点 . 以及波浪线 ~
  4. 保留字符:!*’();:@&=+$,/?#[]

除上述四种字符外,所有其他字符都将被替换成百分号 % + 两位十六进制数。

1
@":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`\r\n\t" // @"" 是 OC 语法, 关注引号中字符即可

这33个字符需要转义, 其中

1
@" \"#%&()+,/:;<>=?@\\|"

是特殊字符转义编码, 一定要转义

1
@"{}^[]`~" 

这些属于不安全字段, 传输过程中某些网关会篡改这些字符, 最好也转义
对于 NSURLComponents 不能解析的字符串有

1
@"[] \"<>%{}|\\^`\r\n\t"

这 16 个字符, 执行 urlComponents.queryItems 为 nil

特殊字符的编码如下:

ASCII 字符 URL-编码
空格 %20
! %21
%22
# %23
$ %24
% %25
& %26
%27
( %28
) %29
* %2A
+ %2B
, %2C
- %2D
. %2E
/ %2F
: %3A
; %3B
< %3C
= %3D
> %3E
? %3F
@ %40
[ %5B
\ %5C
] %5D
^ %5E
_ %5F
` %60
{ %7B
| %7C
} %7D
~ %7E

问题原由

在 url 解析参数时, 对 query 参数做了 [NSString stringByRemovingPercentEncoding] 转义, 替换掉了所有的 %20 转义字符, 然后将转移后的 url 交给 WebView 展示. 然后 webview 在使用 NSURLComponents *urlComponents = [[NSURLComponents alloc] initWithString:url]; 解析 url 时, 发现 url 含有’^|’等字符就直接解析失败, 造成 bug, 解决办法也很简单, 在解析失败的时候, 针对

1
[] \"<>%{}|\\^`\r\n\t

这些字符做重新编码, 然后再使用 NSURLComponents 解析即可, 代码如下

1
2
3
4
5
NSString *specialString = @"[] \"<>%{}|\\^`\r\n\t";
NSCharacterSet *allowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:specialString] invertedSet];
NSString *encoded = [url stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
// 再解析 encoded 即可

参考文档

关于URL编码

-------------本文结束感谢您的阅读-------------

欢迎关注我的其它发布渠道