是Xcode 9中破解的“加法百分比编码”?
在使用Xcode 9 beta 2的Swift 3.x中,使用addingPercentEncoding
会产生意想不到的结果。 CharacterSet.urlPathAllowed
总是包含“:”,所以通过定义addingPercentEncoding
,它永远不应该逃避它。 然而,使用这个代码:
// always true print(CharacterSet.urlPathAllowed.contains(":")) let myString = "info:hello world" let escapedString = myString.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)! print(escapedString)
我得到这些结果:
我得到不良行为的案件
- Xcode 9 beta 2,iOS 9.3
- Xcode 9 beta 2,iOS 11.0
真正
资讯%3Ahello%20world
我得到预期的行为的情况
- Xcode 9 beta 2,iOS 10.3.1
- Xcode 8.3.3,任何iOS
真正
信息:你好%20world
是否有任何解决方法来获得正确尊重给定的addingPercentEncoding
正确addingPercentEncoding
的工作实现?
显然当用作引用的CharacterSet是一个基础的NSCharacterSet类的时候,通过addingPercentEncoding
做了一些未logging的魔法。
所以为了解决这个问题,你需要使你的CharacterSet成为一个纯Swift对象。 为了做到这一点,我会创build一个副本(感谢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) } }
即使它是在.urlPathAllowed
字符集中,转义字符的百分比的原因是,它似乎是严格执行RFC 3986的第3.3节,它说:
在相对path中是允许的(这就是我们所说的“在这里处理),但不在第一个组件。
考虑:
let string = "foo:bar/baz:qux" print(string.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!)
这将符合RFC 3986的规定,在第一个组件中编码百分比,但是允许在后续组件中不编码:
FOO%3Abar /巴兹:qux
文档的方法名称和性质会导致人们得出结论:它只是根据允许的字符的百分比编码,但实际上它看起来像是在考虑它是否是.urlPathAllowed
,并应用了RFC 3986的相对path逻辑。
正如Cœur所说的,你可以通过构build自己的字符集来.urlPathAllowed
,允许使用与.urlPathAllowed
相同的字符,并且不应用任何这种逻辑。