Swift - 编码 URL

Swift - encode URL

提问人:MegaCookie 提问时间:7/3/2014 最后编辑:Bryan ChenMegaCookie 更新时间:11/15/2023 访问量:354177

问:

如果我像这样编码字符串:

var escapedString = originalString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)

它没有逃脱斜线./

我搜索并找到了这个 Objective C 代码:

NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                        NULL,
                        (CFStringRef)unencodedString,
                        NULL,
                        (CFStringRef)@"!*'();:@&=+$,/?%#[]",
                        kCFStringEncodingUTF8 );

有没有一种更简单的方法来编码 URL,如果没有,我如何在 Swift 中编写它?

iOS Swift URLencode

评论


答:

727赞 zaph 7/3/2014 #1

斯威夫特 3

在 Swift 3 中,有addingPercentEncoding

let originalString = "test/test"
let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
print(escapedString!)

输出:

测试%2F测试

斯威夫特 1

在 iOS 7 及更高版本中,有stringByAddingPercentEncodingWithAllowedCharacters

var originalString = "test/test"
var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())
println("escapedString: \(escapedString)")

输出:

测试%2F测试

以下是有用的(反转)字符集:

URLFragmentAllowedCharacterSet  "#%<>[\]^`{|}
URLHostAllowedCharacterSet      "#%/<>?@\^`{|}
URLPasswordAllowedCharacterSet  "#%/:<>?@[\]^`{|}
URLPathAllowedCharacterSet      "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet     "#%<>[\]^`{|}
URLUserAllowedCharacterSet      "#%/:<>?@[\]^`

如果要对一组不同的字符进行转义,请创建一个集合: 添加“=”字符的示例:

var originalString = "test/test=42"
var customAllowedSet =  NSCharacterSet(charactersInString:"=\"#%/<>?@\\^`{|}").invertedSet
var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(customAllowedSet)
println("escapedString: \(escapedString)")

输出:

测试%2Ftest%3D42

验证不在集中的 ascii 字符的示例:

func printCharactersInSet(set: NSCharacterSet) {
    var characters = ""
    let iSet = set.invertedSet
    for i: UInt32 in 32..<127 {
        let c = Character(UnicodeScalar(i))
        if iSet.longCharacterIsMember(i) {
            characters = characters + String(c)
        }
    }
    print("characters not in set: \'\(characters)\'")
}

评论

8赞 thatidiotguy 10/1/2014
难道没有其他人对这段代码要花多长时间完全感到惊讶吗?我的意思是,即使没有选择允许的字符集,方法名称也已经很长了。
52赞 zaph 10/1/2014
不,我更喜欢可理解性,而不是简短的命名。自动完成功能消除了痛苦。 毫无疑问,它的作用。考虑到“大吃一惊”这个词有多长,有趣的评论。stringByAddingPercentEncodingWithAllowedCharacters()
1赞 Julio Garcia 1/31/2016
stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet()) 不能正确编码所有字符 Bryan Chen 的回答是更好的解决方案。
2赞 Akash Kava 3/2/2016
@zaph我添加到字符集,并对每个字符进行了编码。检查了iOS 9,看起来像有问题,我选择了@bryanchen的答案,效果很好!&URLQueryAllowedCharacterSet
5赞 Aaron Brager 11/13/2017
下面的答案使用并且更清洁的 IMO。URLComponentsURLQueryItem
14赞 Bryan Chen 7/3/2014 #2

一切都是一样的

var str = CFURLCreateStringByAddingPercentEscapes(
    nil,
    "test/test",
    nil,
    "!*'();:@&=+$,/?%#[]",
    CFStringBuiltInEncodings.UTF8.rawValue
)

// test%2Ftest

评论

0赞 Kreiri 7/3/2014
您没有第二个参数,也没有得到“无法将表达式的类型'CFString!'转换为类型'CFString!'”?.bridgeToOvjectiveC()
0赞 Bryan Chen 7/3/2014
@Kreiri 为什么需要它?playground 和 REPL 都对我的代码感到满意。
0赞 Kreiri 7/3/2014
我的不是:/(测试版2)
1赞 Sam 11/26/2015
这是一个更好的答案,因为它正确地编码了 &。
4赞 BadPirate 1/2/2015 #3

我自己需要这个,所以我写了一个字符串扩展,它既允许 URLEncoding 字符串,又允许更常见的最终目标,将参数字典转换为“GET”样式的 URL 参数:

extension String {
    func URLEncodedString() -> String? {
        var escapedString = self.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
        return escapedString
    }
    static func queryStringFromParameters(parameters: Dictionary<String,String>) -> String? {
        if (parameters.count == 0)
        {
            return nil
        }
        var queryString : String? = nil
        for (key, value) in parameters {
            if let encodedKey = key.URLEncodedString() {
                if let encodedValue = value.URLEncodedString() {
                    if queryString == nil
                    {
                        queryString = "?"
                    }
                    else
                    {
                        queryString! += "&"
                    }
                    queryString! += encodedKey + "=" + encodedValue
                }
            }
        }
        return queryString
    }
}

享受!

评论

3赞 Sam 11/26/2015
这不会对“&”符号进行编码。在参数中使用“&”将增加查询字符串
0赞 Marián Černý 3/10/2018
这是错误的,它不编码或参数。请检查我的解决方案。&=
3赞 Gaurav Singla 6/6/2016 #4

这个对我有用。

func stringByAddingPercentEncodingForFormData(plusForSpace: Bool=false) -> String? {

    let unreserved = "*-._"
    let allowed = NSMutableCharacterSet.alphanumericCharacterSet()
    allowed.addCharactersInString(unreserved)

    if plusForSpace {
        allowed.addCharactersInString(" ")
    }

    var encoded = stringByAddingPercentEncodingWithAllowedCharacters(allowed)

    if plusForSpace {
        encoded = encoded?.stringByReplacingOccurrencesOfString(" ", withString: "+")
    }
    return encoded
}

我从这个链接中找到了上面的功能:http://useyourloaf.com/blog/how-to-percent-encode-a-url-string/

30赞 AJP 9/29/2016 #5

Swift 4 & 5 (感谢@sumizome的建议。感谢@FD_和@derickito的测试)

var allowedQueryParamAndKey = NSCharacterSet.urlQueryAllowed
allowedQueryParamAndKey.remove(charactersIn: ";/?:@&=+$, ")
paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)

斯威夫特 3

let allowedQueryParamAndKey =  NSCharacterSet.urlQueryAllowed.remove(charactersIn: ";/?:@&=+$, ")
paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)

Swift 2.2(借鉴 Zaph 并更正 url 查询键和参数值)

var allowedQueryParamAndKey =  NSCharacterSet(charactersInString: ";/?:@&=+$, ").invertedSet
paramOrKey.stringByAddingPercentEncodingWithAllowedCharacters(allowedQueryParamAndKey)

例:

let paramOrKey = "https://some.website.com/path/to/page.srf?a=1&b=2#top"
paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)
// produces:
"https%3A%2F%2Fsome.website.com%2Fpath%2Fto%2Fpage.srf%3Fa%3D1%26b%3D2%23top"

这是Bryan Chen回答的简短版本。我猜这是允许控制字符通过,除非它们构成查询字符串中键或值的一部分,此时需要转义它们。urlQueryAllowed

评论

2赞 Marián Černý 3/10/2018
我喜欢 Swift 3 解决方案,但它在 Swift 4 中对我不起作用:“不能在不可变值上使用突变成员:'urlQueryAllowed' 是仅获取属性”。
0赞 sumizome 9/26/2018
@MariánČerný只需使 CharacterSet 可变(使用 ),然后在第二步中调用它。var.remove
0赞 FD_ 9/14/2019
我相信这个和大多数其他解决方案在两次应用该方法时都存在问题,例如在另一个 URL 的参数中包含带有编码参数的 URL 时。
1赞 FD_ 9/21/2019
@AJP我刚刚测试了你所有的片段。Swift 3 和 4 工作正常,但 Swift 2.2 的 Swift 2.2 无法正确将 %20 编码为 %2520。
1赞 derickito 7/18/2020
Swift 4 解决方案在 2020 年 7 月对我有用,使用 Swift 5
51赞 Hong Wei 9/29/2016 #6

斯威夫特 5:

extension String {
    var urlEncoded: String? {
        let allowedCharacterSet = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "~-_."))
        return self.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet)
    }
}

print("\u{48}ello\u{9}world\u{7}\u{0}".urlEncoded!) // prints Hello%09world%07%00
print("The string ü@foo-bar".urlEncoded!) // prints The%20string%20%C3%BC%40foo-bar


评论

3赞 AJP 9/29/2016
您需要在字符串中包含 ' '(空格)
1赞 Thamilan S 4/27/2017
您还需要包括 ^
1赞 Marián Černý 5/13/2021
这是错误的。 成为。例如,控制字符或制表器不会转义。let originalString = "\u{48}ello\u{9}world\u{7}\u{0}""Hello\tworld\u{07}\0"
104赞 Leo Dabus 4/28/2017 #7

可以使用 URLComponents 来避免手动对查询字符串进行百分比编码:

let scheme = "https"
let host = "www.google.com"
let path = "/search"
let queryItem = URLQueryItem(name: "q", value: "Formula One")


var urlComponents = URLComponents()
urlComponents.scheme = scheme
urlComponents.host = host
urlComponents.path = path
urlComponents.queryItems = [queryItem]

if let url = urlComponents.url {
    print(url)   // "https://www.google.com/search?q=Formula%20One"
}

extension URLComponents {
    init(scheme: String = "https",
         host: String = "www.google.com",
         path: String = "/search",
         queryItems: [URLQueryItem]) {
        self.init()
        self.scheme = scheme
        self.host = host
        self.path = path
        self.queryItems = queryItems
    }
}

let query = "Formula One"
if let url = URLComponents(queryItems: [URLQueryItem(name: "q", value: query)]).url {
    print(url)  // https://www.google.com/search?q=Formula%20One
}

评论

7赞 Asa 5/18/2017
这个答案需要更多的关注,因为所有其他答案都存在问题(尽管公平地说,它们可能是当时的最佳实践)。
12赞 Sulthan 3/10/2018
可悲的是,并不总是正确编码。例如,将被编码为 ,而 将被解码为 。因此,请谨慎使用加号。URLQueryItemFormula+OneFormula+OneFormula One
0赞 CouchDeveloper 9/29/2021
@Sulthan具有字符串“Formula+One”,则应编码为“Formula+One”。这是因为“+”位于保留字符集中,而保留字符包含在构成查询组件的“pchar”集中。如果解码将使用 URLComponents 生成“一级方程式”,则;)
1赞 Sulthan 9/29/2021
@CouchDeveloper 这比你想象的要复杂一些。Yu 引用了 URI 规范,但这是关于 URL,这是一个特例。实际上(至少)有两个 URL 规范存在一些冲突。URI 规范本身说:“如果 URI 组件的数据与保留字符作为分隔符的用途冲突,则必须在形成 URI 之前对冲突的数据进行百分比编码。这显然是不正确的,因为加号 URL 编码输出表示一个空格。URLComponents
0赞 CouchDeveloper 9/29/2021
@Sulthan 在 URL 规范中,URL 查询被定义为 ASCII 字符串(序列化器和解析器中只有基本的约束检查)。要弄清楚解析和序列化查询(键值对列表)的规则,我们需要查看 x-www-form-urlencoded。除了这里有一些指导方针之外,规范本身还谈到了 x-www-form-urlencoded:“[这种] 格式在很多方面都是一种异常的怪物,是多年实现事故的结果......” ;)
50赞 iHTCboy 4/28/2017 #8

斯威夫特 3:

let originalString = "http://www.ihtc.cc?name=htc&title=iOS开发工程师"

1. encodingQuery:

let escapedString = originalString.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)

结果:

"http://www.ihtc.cc?name=htc&title=iOS%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88" 

2. 编码URL:

let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)

结果:

"http:%2F%2Fwww.ihtc.cc%3Fname=htc&title=iOS%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88"

评论

0赞 Akshay Phulare 1/2/2018
我使用了第一个解决方案,但我想把我的文本找回来,比如iOS开发工程师。
3赞 Sulthan 1/3/2019
用于对查询参数进行编码不正确,因为它不会对 和 进行编码。对查询参数进行编码时,必须分别正确地对参数名称和值进行编码。这在一般情况下是行不通的。urlHostAllowed?=+
0赞 Bharath 1/6/2019
@Sulthan..你有没有找到任何解决方案/替代方案urlHostAllowed
0赞 Sulthan 1/6/2019
@Bharath 是的,您必须自己构建字符集,例如 stackoverflow.com/a/39767927/669586 或仅使用 .URLComponents
0赞 SoftDesigner 4/20/2020
URLComponents 也不会对 char 进行编码。因此,唯一的选择是手动执行:+CharacterSet.urlQueryAllowed.subtracting(CharacterSet(charactersIn: "+"))
17赞 Alessandro Ornano 3/7/2018 #9

斯威夫特 4:

这取决于您的服务器遵循的编码规则。

Apple 提供了此类方法,但它没有报告它遵循的 RCF 协议类型。

var escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!

按照这个有用的工具,你应该保证你的参数对这些字符进行编码:

  • $(美元符号)变为 %24
  • &(与号)变为 %26
  • + (加号) 变为 %2B
  • ,(逗号)变为 %2C
  • : (冒号) 变为 %3A
  • ;(分号)变为 %3B
  • = (等于) 变为 %3D
  • ?(问号)变为 %3F
  • @(商业 A / At)变为 %40

换句话说,谈到 URL 编码,您应该遵循 RFC 1738 协议

例如,Swift 没有涵盖 + char 的编码,但它适用于这三个 @ : ? chars。

因此,要正确编码每个参数,该选项是不够的,您还应该添加特殊字符,例如:.urlHostAllowed

encodedParameter = parameter.replacingOccurrences(of: "+", with: "%2B")

希望这能帮助那些变得疯狂的人搜索这些信息。

评论

1赞 neobie 1/10/2021
& 符号根本不起作用。会发生什么?
90赞 Marián Černý 3/12/2018 #10

斯威夫特 4 和 5

要对 URL 中的参数进行编码,我发现使用字符集是最简单的选择:.alphanumerics

let urlEncoded = value.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
let url = "http://www.example.com/?name=\(urlEncoded!)"

对 URL 编码使用任何标准字符集(like 或 )都不起作用,因为它们不排除 or 字符。.urlQueryAllowed.urlHostAllowed=&

使用也无法正常工作,因为它不会转义字符。URLComponents+

请注意,通过使用它将对一些不需要编码的字符进行编码(如 、 或 --——参见 2.3。 RFC 3986 中的非保留字符)。我发现使用比构建自定义字符集更简单,并且不介意要编码一些额外的字符。如果这困扰您,请构造一个自定义字符集,如如何对 URL 字符串进行百分比编码中所述,例如:.alphanumerics-._~.alphanumerics

// Store allowed character set for reuse (computed lazily).
private let urlAllowed: CharacterSet =
    .alphanumerics.union(.init(charactersIn: "-._~")) // as per RFC 3986

extension String {
    var urlEncoded: String? {
        return addingPercentEncoding(withAllowedCharacters: urlAllowed)
    }
}

let url = "http://www.example.com/?name=\(value.urlEncoded!)"

警告:参数被强制展开。对于无效的 unicode 字符串,它可能会崩溃。请参阅为什么 String.addingPercentEncoding() 的返回值是可选的?。您可以使用 or 代替强制解包。urlEncodedurlEncoded!urlEncoded ?? ""if let urlEncoded = urlEncoded { ... }

评论

2赞 Dion 12/2/2019
.aphanumerics 成功了,谢谢!所有其他字符集都没有转义 &,这在使用字符串作为 get 参数时会导致问题。
1赞 norbDEV 10/30/2020
适用于 Swift 5.X 和 iOS14
1赞 GenericPtr 9/1/2022
这应该是公认的答案。我浪费了很多时间尝试其他不适用于 = 字符的顶级答案。
0赞 LinusGeffarth 10/17/2022
为什么代替 ?从名称上看,听起来它应该编码......还是有其他问题/优势?.aphanumerics.urlHostAllowed&
0赞 Marián Černý 10/24/2022
使用不转义或字符,如答案中所写。随意自己尝试一下。.urlHostAllowed=&
6赞 CartoonChess 11/7/2018 #11

这在 Swift 5 中对我有用。用例是从剪贴板或类似内容中获取 URL,该 URL 可能已经具有转义字符,但也包含可能导致或失败的 Unicode 字符。URLComponentsURL(string:)

首先,创建一个包含所有 URL 合法字符的字符集:

extension CharacterSet {

    /// Characters valid in at least one part of a URL.
    ///
    /// These characters are not allowed in ALL parts of a URL; each part has different requirements. This set is useful for checking for Unicode characters that need to be percent encoded before performing a validity check on individual URL components.
    static var urlAllowedCharacters: CharacterSet {
        // Start by including hash, which isn't in any set
        var characters = CharacterSet(charactersIn: "#")
        // All URL-legal characters
        characters.formUnion(.urlUserAllowed)
        characters.formUnion(.urlPasswordAllowed)
        characters.formUnion(.urlHostAllowed)
        characters.formUnion(.urlPathAllowed)
        characters.formUnion(.urlQueryAllowed)
        characters.formUnion(.urlFragmentAllowed)

        return characters
    }
}

接下来,使用编码 URL 的方法进行扩展:String

extension String {

    /// Converts a string to a percent-encoded URL, including Unicode characters.
    ///
    /// - Returns: An encoded URL if all steps succeed, otherwise nil.
    func encodedUrl() -> URL? {        
        // Remove preexisting encoding,
        guard let decodedString = self.removingPercentEncoding,
            // encode any Unicode characters so URLComponents doesn't choke,
            let unicodeEncodedString = decodedString.addingPercentEncoding(withAllowedCharacters: .urlAllowedCharacters),
            // break into components to use proper encoding for each part,
            let components = URLComponents(string: unicodeEncodedString),
            // and reencode, to revert decoding while encoding missed characters.
            let percentEncodedUrl = components.url else {
            // Encoding failed
            return nil
        }

        return percentEncodedUrl
    }

}

可以像以下方式进行测试:

let urlText = "https://www.example.com/폴더/search?q=123&foo=bar&multi=eggs+and+ham&hangul=한글&spaced=lovely%20spam&illegal=<>#top"
let url = encodedUrl(from: urlText)

末尾的值:urlhttps://www.example.com/%ED%8F%B4%EB%8D%94/search?q=123&foo=bar&multi=eggs+and+ham&hangul=%ED%95%9C%EA%B8%80&spaced=lovely%20spam&illegal=%3C%3E#top

请注意,保留了 和 间距,对 Unicode 字符进行了编码,原始字符中的 没有双重编码,并且保留了锚点(片段或 )。%20+%20urlText#

编辑:现在检查每个组件的有效性。

0赞 Vrushal Raut 1/18/2019 #12

SWIFT 4.2 版本

有时发生这种情况只是因为 slug 中有空间或通过 API URL 传递的参数没有 URL 编码。

let myString = self.slugValue
                let csCopy = CharacterSet(bitmapRepresentation: CharacterSet.urlPathAllowed.bitmapRepresentation)
                let escapedString = myString!.addingPercentEncoding(withAllowedCharacters: csCopy)!
                //always "info:hello%20world"
                print(escapedString)

注意:别忘了探索 .bitmapRepresentation

12赞 andrewjazbec 2/22/2019 #13

斯威夫特 4.2

快速的单线解决方案。替换为要编码的字符串。originalString

var encodedString = originalString.addingPercentEncoding(withAllowedCharacters: CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[]{} ").inverted)

在线 Playground 演示

评论

0赞 Rakshitha Muranga Rodrigo 3/12/2020
这得益于:您可以检查并尝试解码和编码结果。urldecoder.org
1赞 Marián Černý 5/13/2021
我不认为这是一个正确的实现。例如,编码为 .例如,控制字符或制表器不转义。let originalString = "\u{48}ello\u{9}world\u{7}\u{0}""Hello\tworld\u{07}\0"
0赞 Mike 11/26/2022
为我工作,将 + 转换为 %2B 和其他字符。谢谢。
2赞 jaskiratjd 3/5/2019 #14

let Url = URL(string: urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "")

5赞 Hardik Thakkar 11/13/2019 #15

对于 Swift 5 到字符串的端码

func escape(string: String) -> String {
    let allowedCharacters = string.addingPercentEncoding(withAllowedCharacters: CharacterSet(charactersIn: ":=\"#%/<>?@\\^`{|}").inverted) ?? ""
    return allowedCharacters
}

如何使用?

let strEncoded = self.escape(string: "http://www.edamam.com/ontologies/edamam.owl#recipe_e2a1b9bf2d996cbd9875b80612ed9aa4")
print("escapedString: \(strEncoded)")
2赞 Jenel Ejercito Myers 1/24/2020 #16

这些答案都不适合我。当 url 包含非英文字符时,我们的应用程序崩溃了。

 let unreserved = "-._~/?%$!:"
 let allowed = NSMutableCharacterSet.alphanumeric()
     allowed.addCharacters(in: unreserved)

 let escapedString = urlString.addingPercentEncoding(withAllowedCharacters: allowed as CharacterSet)

根据您尝试执行的操作的参数,您可能只想创建自己的字符集。以上允许使用英文字符,并且-._~/?%$!:

2赞 Mohsin Khubaib Ahmed 6/29/2020 #17

对我有帮助的是,我创建了一个单独的字符串,并将其用于 UTF-8 编码的字符串,即 textToEncode 来生成所需的结果:NSCharacterSet

var queryCharSet = NSCharacterSet.urlQueryAllowed
queryCharSet.remove(charactersIn: "+&?,:;@+=$*()")
    
let utfedCharacterSet = String(utf8String: textToEncode.cString(using: .utf8)!)!
let encodedStr = utfedCharacterSet.addingPercentEncoding(withAllowedCharacters: queryCharSet)!
    
let paramUrl = "https://api.abc.eu/api/search?device=true&query=\(escapedStr)"

评论

1赞 Amit Thakur 2/22/2022
经过 4 天的挣扎,这段代码确实有帮助。谢谢Mohsin。你是冠军。祝你好运,继续编码。再次感谢。请为编码人员投票。
-4赞 Dilip 1/6/2021 #18

斯威夫特 5你可以试试。afURLQueryAllowed 选项,如果要对字符串进行编码,如下所示

let testString = "6hAD9/RjY+SnGm&B"
let escodedString = testString.addingPercentEncoding(withAllowedCharacters: .afURLQueryAllowed)
print(escodedString!) 

编码的字符串将类似于 en6hAD9%2FRjY%2BSnGm%26B

评论

2赞 muhasturk 6/18/2021
由于 afURLQueryAllowed 在第三方 Alamofire 上被否决。
-2赞 Lgufan 4/25/2021 #19

版本:Swift 5

// space convert to +
let mstring = string.replacingOccurrences(of: " ", with: "+")
// remove special character
var allowedQueryParamAndKey = NSCharacterSet.urlQueryAllowed
allowedQueryParamAndKey.remove(charactersIn: "!*'\"();:@&=+$,/?%#[]%")
return mstring.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey) ?? mstring  

评论

1赞 Eric Aya 4/25/2021
你说 Swift 5,但后来你使用 NSCharacterSet 而不是 CharacterSet,这是一个奇怪的选择。此外,您首先将空格替换为 + 字符,然后在要删除的字符列表中我们看到一个空格,因此第一个操作是多余的。
0赞 Lgufan 4/27/2021
使用 NSCharacterSet 而不是 CharacterSet,因为参考了其他answers.@EricAya
0赞 Robin Daugherty 2/19/2023
+可用于表示空格,但需要正确转义现有的实例。这个答案是不该做什么的一个例子。+
0赞 meomeomeo 9/15/2023 #20

我曾经遇到过这样的字符串问题(其中某些部分已经编码)。%5B×××%5D

我花了一个小时才意识到它可以很容易地解决:

extension String {
    var decodeThenEncodeURL: String {
        removingPercentEncoding?.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? self
    }
}
  • 输入:https://www.google.com/search?q=%5B×××%5D
  • 输出:https://www.google.com/search?q=%5B%C3%97%C3%97%C3%97%5D
-1赞 Zev003 11/15/2023 #21

这更好,更权威。它引用了Almofire URLEncodedFormEncoder.swift

extension CharacterSet {
    /// Creates a CharacterSet from RFC 3986 allowed characters.
    ///
    /// RFC 3986 states that the following characters are "reserved" characters.
    ///
    /// - General Delimiters: ":", "#", "[", "]", "@", "?", "/"
    /// - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
    ///
    /// In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow
    /// query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/"
    /// should be percent-escaped in the query string.
    public static let afURLQueryAllowed: CharacterSet = {
        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
        let subDelimitersToEncode = "!$&'()*+,;="
        let encodableDelimiters = CharacterSet(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")

        return CharacterSet.urlQueryAllowed.subtracting(encodableDelimiters)
    }()
}