Swift - 编码URL

时间:2014-07-03 10:56:03

标签: ios swift urlencode

如果我对这样的字符串进行编码:

var escapedString = originalString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)

它不会逃避斜杠/

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

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

是否有更简单的方法对URL进行编码,如果没有,我该如何在Swift中编写?

19 个答案:

答案 0 :(得分:527)

Swift 3

在Swift 3中有addingPercentEncoding

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

输出:

  

测试%2Ftest

Swift 1

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

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

输出:

  

测试%2Ftest

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

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)\'")
}

答案 1 :(得分:46)

您可以使用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
}

答案 2 :(得分:32)

斯威夫特3:

let allowedCharacterSet = (CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[] ").inverted)

if let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) {
//do something with escaped string
}

答案 3 :(得分:24)

Swift 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。 encodingURL:

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"

答案 4 :(得分:18)

Swift 4

要在URL中对参数进行编码,我使用.alphanumerics字符集找到最简单的选项:

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

使用任何标准字符集进行网址编码(例如URLQueryAllowedCharacterSetURLHostAllowedCharacterSet)都不起作用,因为它们不会排除=&个字符。

注意,使用.alphanumerics,它会对一些不需要编码的字符进行编码(例如-._~ - 请参阅 2.3。RFC 3986中未保留的字符)。我发现使用.alphanumerics比构造自定义字符集更简单,并且不介意要编码一些其他字符。如果这让您感到困扰,请构建一个自定义字符集,如How to percent encode a URL String中所述,例如:

var allowed = CharacterSet.alphanumerics
allowed.insert(charactersIn: "-._~") // as per RFC 3986
let encoded = parameter.addingPercentEncoding(withAllowedCharacters: allowed)
let url = "http://www.example.com/?name=\(encoded!)"

警告: encoded参数已强制解包。对于无效的unicode字符串,它可能会崩溃。见Why is the return value of String.addingPercentEncoding() optional?。您可以使用encoded!或使用encoded ?? ""来代替强行展开if let encoded = ...

答案 5 :(得分:12)

一切都是一样的

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

// test%2Ftest

答案 6 :(得分:10)

Swift 4(未经测试 - 请评论是否有效。感谢@sumizome提出建议)

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

Swift 3

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

Swift 2.2 (借用Zaph&#39;并更正网址查询键和参数值)

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"

这是布莱恩·陈的答案的缩短版。我猜测urlQueryAllowed允许控制字符是正常的,除非它们构成查询字符串中的键或值的一部分,此时它们需要被转义。

答案 7 :(得分:8)

斯威夫特4:

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

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

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

遵循这个有用的tool,你应该保证为你的参数编码这些字符:

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

换句话说,谈到网址编码,您应该遵循RFC 1738 protocol

Swift并未涵盖+ char的编码,但它适用于这三个 @:?字符。

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

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

希望这可以帮助那些疯狂的人搜索这些信息。

答案 8 :(得分:4)

我自己需要这个,所以我编写了一个String扩展,它允许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
    }
}

享受!

答案 9 :(得分:2)

这个适合我。

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/

答案 10 :(得分:2)

Swift 4.2

一种快速的单行解决方案。将originalString替换为您要编码的字符串。

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

Online Playground Demo

答案 11 :(得分:0)

SWIFT 4.2

有时发生这种情况的原因是,在通过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 :(得分:0)

为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)")

答案 13 :(得分:0)

这些答案都不对我有用。网址包含非英语字符时,我们的应用程序崩溃了。

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

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

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

答案 14 :(得分:0)

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

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)"

答案 15 :(得分:-1)

这在Swift 4.2中为我工作。用例是从剪贴板或类似的网址中获取一个URL,该URL可能已经转义了字符,但还包含Unicode字符,这可能导致URL(string:)失败。

func encodedUrl(from string: String) -> URL? {
    // Remove preexisting encoding
    guard let decodedString = string.removingPercentEncoding,
        // Reencode, to revert decoding while encoding missed characters
        let percentEncodedString = decodedString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
            // Coding failed
            return nil
    }
    // Create URL from encoded string, or nil if failed
    return URL(string: percentEncodedString)
}

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

url末尾的值:https://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

请注意,%20+的间距均会保留,对Unicode字符进行编码,并且原始%20中的urlText不会进行双重编码。

注意事项:这是快捷方式,因为它在整个URL上使用.urlQueryAllowed;它还假定该URL已经在浏览器中工作。明智地使用!我也乐于接受建议(我停止使用URLComponents切掉整个URL,应用单个字符集并重新组装)。

答案 16 :(得分:-1)

Swift 5 如果你想像下面这样编码字符串,你可以尝试 .afURLQueryAllowed 选项

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

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

答案 17 :(得分:-2)

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

答案 18 :(得分:-2)

版本: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