URL 查询参数是 URL 中问号 之后的部分,通常以 key=value 的形式出现,多个参数用 & 分隔。
https://example.com/search?query=ios&category=dev&page=1

(图片来源网络,侵删)
在 iOS 中,处理这些参数主要有三种方式:
- Foundation 的 URLComponents (推荐,最现代、最安全)
- 传统的字符串分割方法 (简单但不健壮)
- 第三方库 (如 Alamofire,网络请求框架中内置)
使用 URLComponents (推荐)
URLComponents 是 Apple 官方提供的类,专门用于解析和构建 URL,它能正确处理 URL 编码(如空格变为 %20 或 ),是处理 URL 参数最安全、最可靠的方式。
核心属性
queryItems: 一个[URLQueryItem]数组,代表所有的查询参数。query: 一个String,代表原始的查询字符串( 之后的部分)。
解析查询参数
步骤:
- 创建一个
URLComponents实例,并传入你的 URL 字符串。 - 检查
url属性是否为nil,确保 URL 是有效的。 - 访问
queryItems属性,它会自动将查询字符串解析成URLQueryItem数组。 - 遍历
queryItems,通过name和value获取参数名和值。
示例代码:

(图片来源网络,侵删)
import Foundation
let urlString = "https://example.com/search?query=ios%20programming&category=dev&page=1&sort=desc"
// 1. 创建 URLComponents 实例
guard var urlComponents = URLComponents(string: urlString) else {
print("无效的 URL")
return
}
// 2. 检查 URL 是否有效 (urlComponents.url 不为 nil)
// 在这个例子中,我们主要关心 queryItems,所以可以跳过这个检查,但实际应用中建议加上
// 3. 获取查询参数数组
guard let queryItems = urlComponents.queryItems else {
print("URL 没有查询参数")
return
}
// 4. 遍历并解析参数
var parameters: [String: String] = [:]
for item in queryItems {
// URLQueryItem 的 value 是可选的,因为有些参数可能只有 key 没有 value (e.g., ?flag)
if let value = item.value {
parameters[item.name] = value
}
}
// 打印结果
print(parameters)
// 输出: ["query": "ios programming", "category": "dev", "page": "1", "sort": "desc"]
// 你也可以直接通过 name 来查找某个特定的参数
if let query = urlComponents.queryItems?.first(where: { $0.name == "query" })?.value {
print("搜索关键词是: \(query)")
// 输出: 搜索关键词是: ios programming
}
优点:
- 自动解码: 自动处理 URL 编码,将
ios%20programming还原为ios programming。 - 健壮性: 能正确处理格式错误的 URL 和参数。
- 类型安全:
URLQueryItem结构清晰,不易出错。 - 官方推荐: 是 Apple 推荐的标准做法。
传统的字符串分割方法
这种方法不使用 URLComponents,而是通过 components(separatedBy:) 来手动分割字符串,虽然简单,但非常脆弱,不推荐在生产环境中使用。
示例代码:
import Foundation
let urlString = "https://example.com/search?query=ios%20programming&category=dev&page=1"
// 1. 从 URL 字符串中提取查询部分
guard let queryString = urlString.components(separatedBy: "?").last else {
print("URL 中没有查询参数")
return
}
// 2. 按 "&" 分割成 "key=value" 对
let keyValuePairs = queryString.components(separatedBy: "&")
var parameters: [String: String] = [:]
for pair in keyValuePairs {
// 3. 按 "=" 分割成 key 和 value
let components = pair.components(separatedBy: "=")
if components.count == 2 {
let key = components[0]
// 4. 手动解码 (使用 removingPercentEncoding)
let value = components[1].removingPercentEncoding ?? ""
parameters[key] = value
}
}
print(parameters)
// 输出: ["query": "ios programming", "category": "dev", "page": "1"]
缺点:

(图片来源网络,侵删)
- 脆弱: URL 中有 或
&出现在参数值中(虽然不常见但可能),解析就会失败。 - 手动解码: 容易忘记使用
removingPercentEncoding,导致解码失败。 - 代码冗长: 需要大量的字符串操作和边界条件检查。
构建带查询参数的 URL
除了解析,URLComponents 同样擅长构建带有查询参数的 URL。
示例代码:
import Foundation
// 1. 创建一个基础 URL
var urlComponents = URLComponents()
urlComponents.scheme = "https"
urlComponents.host = "api.example.com"
urlComponents.path = "/v1/users"
// 2. 创建查询参数数组
let queryItems = [
URLQueryItem(name: "id", value: "123"),
URLQueryItem(name: "fields", value: "name,email,profile"), // 值中有逗号也没关系
URLQueryItem(name: "active", value: "true") // 布尔值作为字符串
]
urlComponents.queryItems = queryItems
// 3. 从 URLComponents 生成最终的 URL 字符串
if let url = urlComponents.url {
let finalUrlString = url.absoluteString
print(finalUrlString)
// 输出: https://api.example.com/v1/users?id=123&fields=name,email,profile&active=true
}
注意:
当你设置 queryItems 时,URLComponents 会自动为你进行 URL 编码,如果你的值是 "John Doe",它会被自动编码为 "John%20Doe"。
在 URL Scheme 中处理查询参数
URL Scheme 用于 App 间的跳转,myapp://product?id=555&open=true,处理方式与普通 HTTP URL 完全相同,都是使用 URLComponents。
示例代码:
import UIKit
// 假设这是从另一个 App 收到的 URL
let deepLinkUrl = "myapp://product?id=555&open=true"
guard var components = URLComponents(string: deepLinkUrl),
let queryItems = components.queryItems else {
print("无效的深度链接或无参数")
return
}
if let productId = queryItems.first(where: { $0.name == "id" })?.value,
let shouldOpen = queryItems.first(where: { $0.name == "open" })?.value {
print("准备打开产品 ID: \(productId)")
print("是否应该直接打开: \(shouldOpen)")
// 在这里可以根据参数执行相应的逻辑,比如跳转到某个产品详情页
// navigationController?.pushViewController(ProductDetailViewController(id: productId), animated: true)
}
总结与最佳实践
| 方法 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
URLComponents |
安全、健壮、自动编解码、官方推荐 | 代码量比字符串方法稍多 | 所有场景,无论是解析还是构建 URL,都应作为首选。 |
| 字符串分割 | 简单直观,无需额外对象 | 脆弱、易错、需手动编解码 | 快速原型验证或非常简单的、可控的 URL。 |
| 第三方库 | 通常与网络请求集成,使用方便 | 增加项目依赖 | 如果你已经在使用 Alamofire 等网络库,可以利用它们内置的参数处理功能。 |
核心要点:
- 始终使用
URLComponents:它能让你避免 90% 的 URL 处理 bug。 - 处理可选值:
URLQueryItem.value是String?,URLComponents.url也是URL?,务必使用guard let或if let进行安全解包。 - 理解 URL 编码:知道
%20代表空格,%3F代表 等。URLComponents会为你处理好这一切,但你应该理解其背后的原理。 - 构建 URL 时:先设置
scheme,host,path,然后再添加queryItems,这样逻辑最清晰。
