Xcode 9中的“addsPercentEncoding”被破坏了吗?

问题描述 投票:5回答:2

在Swift 3.x中使用xcode 9 beta 2,使用addingPercentEncoding会产生意想不到的结果。 CharacterSet.urlPathAllowed总是包含“:”,因此根据addingPercentEncoding的定义,它永远不应该逃脱它。然而,使用此代码:

// always true
print(CharacterSet.urlPathAllowed.contains(":"))
let myString = "info:hello world"
let escapedString = myString.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!
print(escapedString)

我得到了那些结果:

cases where I get an undesirable behavior

  • Xcode 9 beta 2,iOS 9.3
  • Xcode 9 beta 2,iOS 11.0 真正 资讯%3Ahello%20world

cases where I get the expected behavior

  • Xcode 9 beta 2,iOS 10.3.1
  • Xcode 8.3.3,任何iOS 真正 信息:你好%20world

是否有任何解决方法来获得正确尊重给定addingPercentEncodingallowedCharacters的工作实现?

ios swift urlencode xcode9-beta
2个回答
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)
    }
}

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逻辑。

© www.soinside.com 2019 - 2024. All rights reserved.