Swift encode URL:5个致命错误及如何避免

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Swift 编码 URL:为什么你的代码在西里尔字母和空格上会出错



每一位在 Swift 中发送过网络请求的开发者都曾面临过这种痛苦:你构建了一个 URL,添加了参数,但服务器返回了 400 错误,或者更糟糕的是,它默默地忽略了请求。听起来很熟悉?大多数情况下,问题都出在 URL 编码上。表面上看很简单——取一个字符串,把空格替换成 %20,就完成了。但 Swift(和其他严格的语言一样)不允许马虎的工作。



在这篇文章中,我们将深入分析 Swift 编码 URL 时最常见的 5 个错误,它们在 Stack Overflow 上获得了数千次的浏览量。你将学会如何避免这些错误,并编写出能够处理任何数据(从英文字母到复杂的西里尔字母和特殊字符)的可靠代码。



错误 #1:使用 addingPercentEncoding 并传入错误的字符集



这可能是最常见的陷阱。许多初学者看到 addingPercentEncoding(withAllowedCharacters:) 方法时心想:“哦,完美!”。但他们为整个 URL 传入了 .urlHostAllowed 或 .urlPathAllowed。结果是程序崩溃或请求错误。



为什么这行不通?



URL 的每个部分(协议、主机、路径、查询参数)都有其允许的字符集。如果你把整个 URL 当作主机来编码,你会丢失斜杠和冒号。如果你把它当作路径来编码,你会破坏查询字符串。



// ❌ 错误:将整个 URL 编码为主机let urlString = "https://example.com/path?name=Ivan & surname=Petrov"let encoded = urlString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)// 结果:"https%3A%2F%2Fexample.com%2F%D0%BF%D1%83%D1%82%D1%8C%3Fname%3D%D0%98%D0%B2%D0%B0%D0%BD%20%26%20%D1%84%D0%B0%D0%BC%D0%B8%D0%BB%D0%B8%D1%8F%3D%D0%9F%D0%B5%D1%82%D1%80%D0%BE%D0%B2"// 服务器无法理解这样的 URL


记住黄金法则:分别编码 URL 的每个部分或者使用 URLComponents。



正确做法:使用 URLComponents



// ✅ 正确:使用 URLComponentsvar components = URLComponents()components.scheme = "https"components.host = "example.com"components.path = "/path"components.queryItems = [    URLQueryItem(name: "name", value: "Ivan & Petrov"),    URLQueryItem(name: "surname", value: "Ivanov")]

if let url = components.url { print(url.absoluteString) // "https://example.com/%D0%BF%D1%83%D1%82%D1%8C?name=%D0%98%D0%B2%D0%B0%D0%BD%20%26%20%D0%9F%D0%B5%D1%82%D1%80%D0%BE%D0%B2&%D1%84%D0%B0%D0%BC%D0%B8%D0%BB%D0%B8%D1%8F=%D0%98%D0%B2%D0%B0%D0%BD%D0%BE%D0%B2"}


URLComponents 会自动为每个组件应用正确的百分比编码。这能省去你很多麻烦,也让代码更清晰。



错误 #2:忽略 queryItems 而手动构建字符串



“我为什么需要这些组件?我直接用 + 拼接字符串就行了”。听起来很熟悉?这就引出了第二个常见错误。手动构建查询字符串是通往 Bug 的直接途径。



// ❌ 错误:手动构建查询字符串let name = "Ivan & Petrov"let query = "name=\(name)&age=25"let urlString = "https://example.com?\(query)"// 问题:name 中的与号 & 会被解释为参数分隔符


即使你替换了空格,你也会忘记处理 &、#、? 和其他特殊字符。如果参数来自用户呢?等待你的将是注入和损坏的请求。



解决方案:始终使用 queryItems



// ✅ 正确:queryItems 为你处理所有工作var components = URLComponents(string: "https://example.com")!components.queryItems = [    URLQueryItem(name: "name", value: "Ivan & Petrov"),    URLQueryItem(name: "age", value: "25"),    URLQueryItem(name: "q", value: "Swift encode URL tutorial")]

if let url = components.url { print(url.absoluteStr)

博客

书籍推荐