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

如何将空格与+转为URL编码?解决URLQueryItem编码失效问题

解决URLQueryItem无法正确编码+和空格的问题

默认的URLQueryItem会按照RFC 3986规则处理编码:空格会被转为+,而+字符会直接保留不编码,这和你需要的「空格编码为%20、+编码为%2B」需求不符。可以通过以下两种方式解决:

方案一:手动构建编码后的查询字符串

自定义编码逻辑,对每个参数值做针对性处理,再拼接成查询字符串:

// 自定义参数编码函数
func encodeQueryValue(_ value: String) -> String? {
    // 先替换空格为%20
    let spaceEncoded = value.replacingOccurrences(of: " ", with: "%20")
    // 替换+为%2B
    let plusEncoded = spaceEncoded.replacingOccurrences(of: "+", with: "%2B")
    // 处理其他需要编码的特殊字符(排除+,避免被再次保留)
    let allowedChars = CharacterSet.urlQueryAllowed.subtracting(CharacterSet(charactersIn: "+"))
    return plusEncoded.addingPercentEncoding(withAllowedCharacters: allowedChars)
}

// 构建完整URL
let baseURL = URL(string: "https://your-server.com/api")!
var components = URLComponents(url: baseURL, resolvingAgainstBaseURL: true)!

// 定义参数
let parameters = [
    "param1": "text with spaces",
    "param2": "text+with+pluses"
]

// 拼接编码后的查询项
let encodedQuery = parameters.compactMap { key, value -> String? in
    guard let encodedVal = encodeQueryValue(value) else { return nil }
    let encodedKey = key.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? key
    return "\(encodedKey)=\(encodedVal)"
}.joined(separator: "&")

components.percentEncodedQuery = encodedQuery

// 最终可用的URL
if let finalURL = components.url {
    print(finalURL.absoluteString)
    // 输出示例:https://your-server.com/api?param1=text%20with%20spaces&param2=text%2Bwith%2Bpluses
}

方案二:扩展URLComponents实现自动编码

通过扩展URLComponents,自定义customQueryItems属性,让它自动应用你的编码规则:

extension URLComponents {
    var customQueryItems: [URLQueryItem]? {
        get { queryItems }
        set {
            guard let items = newValue else {
                percentEncodedQuery = nil
                return
            }
            percentEncodedQuery = items.compactMap { item -> String? in
                guard let encodedVal = self.encodeQueryValue(item.value ?? "") else { return nil }
                let encodedKey = item.name.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? item.name
                return "\(encodedKey)=\(encodedVal)"
            }.joined(separator: "&")
        }
    }
    
    private func encodeQueryValue(_ value: String) -> String? {
        let spaceEncoded = value.replacingOccurrences(of: " ", with: "%20")
        let plusEncoded = spaceEncoded.replacingOccurrences(of: "+", with: "%2B")
        let allowedChars = CharacterSet.urlQueryAllowed.subtracting(CharacterSet(charactersIn: "+"))
        return plusEncoded.addingPercentEncoding(withAllowedCharacters: allowedChars)
    }
}

使用时直接设置customQueryItems即可:

let baseURL = URL(string: "https://your-server.com/api")!
var components = URLComponents(url: baseURL, resolvingAgainstBaseURL: true)!

components.customQueryItems = [
    URLQueryItem(name: "param1", value: "text with spaces"),
    URLQueryItem(name: "param2", value: "text+with+pluses")
]

if let finalURL = components.url {
    // 使用finalURL发起请求
}

两种方案的核心都是先手动替换空格和+为目标编码,再处理其他特殊字符,确保最终的URL参数完全符合服务器的解析要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 06:47:40