addingPercentEncoding
会产生意外结果。 CharacterSet.urlPathAllowed
始终包含":",因此根据addingPercentEncoding
的定义,它永远不会逃脱它。然而,使用此代码:
// always true
print(CharacterSet.urlPathAllowed.contains(":"))
let myString = "info:hello world"
let escapedString = myString.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!
print(escapedString)
我得到了那些结果:
真
信息%3Ahello%20world
真
信息:你好%20world
是否有任何解决方法可以使addingPercentEncoding
的工作实施正确地尊重给定的allowedCharacters
?
答案 0 :(得分:9)
当用作引用的CharacterSet是基础NSCharacterSet类时,addingPercentEncoding
显然有一些未记录的魔法。
因此要解决这个魔法,你需要让你的CharacterSet成为一个纯粹的Swift对象。为此,我将创建一个副本(感谢Martin R!),这样邪恶的魔法就消失了:
let myString = "info:hello world"
let csCopy = CharacterSet(bitmapRepresentation: CharacterSet.urlPathAllowed.bitmapRepresentation)
let escapedString = myString.addingPercentEncoding(withAllowedCharacters: csCopy)!
//always "info:hello%20world"
print(escapedString)
作为扩展名:
extension String {
func safeAddingPercentEncoding(withAllowedCharacters allowedCharacters: CharacterSet) -> String? {
// using a copy to workaround magic: https://stackoverflow.com/q/44754996/1033581
let allowedCharacters = CharacterSet(bitmapRepresentation: allowedCharacters.bitmapRepresentation)
return addingPercentEncoding(withAllowedCharacters: allowedCharacters)
}
}
答案 1 :(得分:7)
现在转出:
字符的百分比原因是.urlPathAllowed
现在严格遵守RFC 3986,这在第3.3节“路径”中说明:
此外,URI引用(第4.1节)可以是相对路径引用,在这种情况下,第一个路径段不能包含冒号(“:”)字符。
因此,:
在相对路径中是允许的(这是我们在这里处理的),但不是在第一个组件中。
考虑:
let string = "foo:bar/baz:qux"
print(string.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!)
那将符合RFC 3986,百分比编码第一个组件中的:
,但允许它在后续组件中未编码:
foo%3Abar/baz:qux
此字符集不是仅根据集合中的字符进行百分比编码,而是实际应用RFC 3986的相对路径逻辑。但正如Cœur所说,如果需要,可以通过使用与.urlPathAllowed
相同的允许字符构建自己的字符集来绕过此逻辑,并且新字符集将不会应用此RFC 3986逻辑。