You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS网络请求:CharacterSet与URLQueryItem选型及编码异常问题求助

解决URL重复编码问题 + URLQueryItem使用指南

Hey there! Let's tackle your problem first, then dive into how to use URLQueryItem the right way.

为什么你的%20变成了%2520?

The issue here is double encoding. Your original URL already has %20 (the encoded version of a space). When you call addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), this method encodes the % character itself into %25—so %20 gets turned into %2520. The server receives this garbled value and can't parse it correctly, hence the wrong response.

快速修复:先解码再编码

If you need to work with the existing URL string, you can first decode it to get back the original characters, then re-encode properly:

let originalUrl = "http://analytics.abc.io/acct?start_date=2017-11-15&aff=ABC%20Telecom"

// Step 1: Decode the original URL to get raw characters (turns %20 back to space)
if let decodedUrl = originalUrl.removingPercentEncoding {
    // Step 2: Re-encode only the necessary characters
    if let encodedUrl = decodedUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
        if let finalUrl = URL(string: encodedUrl) {
            print(finalUrl)
            // Output: http://analytics.abc.io/acct?start_date=2017-11-15&aff=ABC%20Telecom
            // Now your request should return correct data
        }
    }
}

更规范的方案:用URLComponents + URLQueryItem

Apple strongly recommends using URLComponents and URLQueryItem to build URLs. This approach handles encoding automatically, so you never have to worry about double encoding or manual mistakes.

What is URLQueryItem?

URLQueryItem represents a single key-value pair in a URL's query string. Each item has a name (the parameter key) and a value (the parameter's raw value—no need to pre-encode it).

Step-by-Step Usage

  1. Initialize URLComponents with your base URL parts (scheme, host, path)
  2. Create URLQueryItem instances for each parameter, using raw values (e.g., spaces as actual spaces, not %20)
  3. Assign the query items to the components' queryItems property
  4. Extract the final URL from the components

Example Code:

// 1. Build the base URL components
var urlComponents = URLComponents()
urlComponents.scheme = "http"
urlComponents.host = "analytics.abc.io"
urlComponents.path = "/acct"

// 2. Create query items with raw values
let queryItems = [
    URLQueryItem(name: "start_date", value: "2017-11-15"),
    URLQueryItem(name: "aff", value: "ABC Telecom") // Use the raw string with space
]

// 3. Attach query items to components
urlComponents.queryItems = queryItems

// 4. Get the final URL
if let finalUrl = urlComponents.url {
    print(finalUrl)
    // Output: http://analytics.abc.io/acct?start_date=2017-11-15&aff=ABC%20Telecom
    // This URL will work correctly for your request
}

Bonus Tips for URLQueryItem

  • If you pass nil as the value, the parameter will be omitted entirely
  • If you pass an empty string as value, it will generate a parameter like key=
  • Always use raw values for value—let URLComponents handle encoding for you. Avoid passing pre-encoded strings, as this can lead to unexpected double encoding.

内容的提问来源于stack exchange,提问作者Huy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:00:39