Xcode 9中的"addsPercentEncoding"被破坏了吗?

Cœu*_*œur 5 urlencode ios swift xcode9-beta

在使用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)
Run Code Online (Sandbox Code Playgroud)

我得到了那些结果:

我得到不良行为的情况

  • 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正确尊重给定的工作实现allowedCharacters

Cœu*_*œur 11

显然,addingPercentEncoding当用作引用的CharacterSet是底层的NSCharacterSet类时,会有一些未记录的魔法.

因此,要解决这个魔法,你需要让你的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)
Run Code Online (Sandbox Code Playgroud)

作为扩展:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 有趣的观察!注意,也可以用`let cs = CharacterSet(bitmapRepresentation:CharacterSet.urlPathAllowed.bitmapRepresentation)创建一个副本. (2认同)

Rob*_*Rob 8

:即使它在.urlPathAllowed字符集中,它是逃避字符的百分比的原因是它似乎严格执行RFC 3986的第3.3节,其中说明:在相对路径中允许(这是我们在这里处理的) ),但不是在第一个组件中.

考虑:

let string = "foo:bar/baz:qux"
print(string.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!)
Run Code Online (Sandbox Code Playgroud)

这将符合RFC 3986,百分比编码:第一个组件,但允许它在后续组件中未编码:

FOO%3Abar /巴兹:qux

文档的方法名称和性质将导致人们得出结论,它的百分比编码完全基于允许的字符,但实际上它看起来确实在考虑它是否是a .urlPathAllowed,并应用RFC 3986的相对路径逻辑.

正如Cœur所说,你可以通过使用相同的允许字符构建自己的字符集来绕过这一点:,并且它不适用于任何这种逻辑.

  • 哦,这真的解释了我在其他一些问题中注意到的问题......哇,文档真的很误导. (3认同)