You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

相同参数调用addingPercentEncoding为何编码结果不一致?

问题

以下Swift代码示例:

let path1 = "[path:test]"
var set = CharacterSet()
set.formUnion(.urlPathAllowed)

let encodedPath1 = path1.addingPercentEncoding(withAllowedCharacters: set)
let encodedPath2 = path1.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)

print("Encoded Path 1: \(String(describing: encodedPath1))")
print("Encoded Path 2: \(String(describing: encodedPath2))")

运行后输出结果如下:

Encoded Path 1: Optional("%5Bpath:test%5D")
Encoded Path 2: Optional("%5Bpath%3Atest%5D")

可以看到两次调用addingPercentEncoding的编码结果不一致,第一个示例中的:未被编码,第二个示例中的:被编码为%3A,这是为什么?

解答

这是因为Swift的CharacterSet对.urlPathAllowed这类预定义集合采用了特殊内部优化:它们被实现为反转集合——不会直接存储所有允许的字符(Unicode字符数量庞大,这样做效率极低),而是存储一小部分被禁止的字符,默认所有其他字符都属于允许范围。

当你创建一个空的CharacterSet(这是标准的「包含型」集合,初始不包含任何字符),再调用formUnion(.urlPathAllowed)时,这个操作会把反转集合转换为标准的包含型集合。但转换过程无法完全复刻原反转集合的逻辑,最终生成的集合意外包含了原.urlPathAllowed所排除的字符(比如:),所以第一个示例中的:不会被编码。

而直接使用.urlPathAllowed时,它会按照原反转集合的规则工作::属于被禁止的字符,因此会被编码。

解决方法

  • 若只需使用.urlPathAllowed的默认规则,直接引用即可,像第二个示例那样。
  • 若需要基于.urlPathAllowed扩展允许的字符,不要从空集合开始,而是直接复制预定义集合再修改:
var set = CharacterSet.urlPathAllowed
// 比如添加允许冒号
set.insert(":")

内容的提问来源于stack exchange,提问作者user501836

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 19:52:33