【问题标题】:is `addingPercentEncoding` broken in Xcode 9?Xcode 9 中的“addingPercentEncoding”是否损坏?
【发布时间】:2017-06-26 07:40:15
【问题描述】:

在带有 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 测试版 2,iOS 11.0

    是的
    info%3Ahello%20world

我得到预期行为的情况

  • Xcode 9 beta 2,iOS 10.3.1
  • Xcode 8.3.3,任何 iOS

    是的
    信息:你好%20world

是否有任何解决方法来获得addingPercentEncoding 的有效实现,以正确尊重给定的allowedCharacters

【问题讨论】:

    标签: ios swift urlencode xcode9-beta


    【解决方案1】:

    当用作引用的 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)
        }
    }
    

    【讨论】:

    • 有趣的观察!请注意,还要使用let cs = CharacterSet(bitmapRepresentation: CharacterSet.urlPathAllowed.bitmapRepresentation) 创建一个副本
    • 很好的解决方案!
    【解决方案2】:

    它现在百分比转义: 字符的原因是.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 逻辑。

    【讨论】:

    • 哦,这确实解释了我在其他问题中注意到的问题......哇,文档真的很误导。
    猜你喜欢
    • 2018-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多