iOS天气API应用:如何处理URL请求特殊字符避免崩溃?
解决URL特殊字符适配问题
你的问题核心是URL不支持直接包含Unicode特殊字符,像ñ、é这类字符必须转换成百分号编码(Percent Encoding)才能被服务器正确解析,直接拼接会导致URL无效,进而触发崩溃。下面是具体的修复方案:
核心修复步骤
- 替换手动处理空格的逻辑,用系统自带的URL编码方法——它能同时处理空格和所有特殊字符,比手动遍历更可靠。
- 对城市名称进行百分号编码,确保所有非URL安全字符都被转换。
- 避免强制解包URL(原代码中的
!),改用可选绑定处理,防止无效URL引发崩溃。
修改后的完整代码
class WeatherClass: ObservableObject { @Published var weatherAddress: String = "" @Published var weatherDays: [WeatherDays] = [] @Published var city: String = "" func fetch() { // 1. 去掉前后空白字符,然后进行URL编码 guard let encodedCity = city.trimmingCharacters(in: .whitespacesAndNewlines) .addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { // 编码失败时的处理(比如输入为空) return } let apiKey = "AP8LUYMSTHFQAF" // 2. 用编码后的城市名构建URL,使用可选绑定避免强制解包 guard let url = URL(string: "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/\(encodedCity)?key=\(apiKey)") else { // URL构建失败时的处理 return } URLSession.shared.dataTask(with: url) { data, response, error in guard let data = data else { return } if let weather = try? JSONDecoder().decode(WeatherData.self, from: data) { DispatchQueue.main.async { self.weatherAddress = weather.resolvedAddress self.weatherDays = weather.days } } }.resume() // 原代码缺失此方法,会导致网络请求不执行 } } struct searchBarUI: View { @ObservedObject var weatherModel: WeatherClass var body: some View { TextField("Search city", text: $weatherModel.city) .frame(height:30) .multilineTextAlignment(.center) .background() .cornerRadius(25) .padding(.horizontal) } }
关键代码解释
trimmingCharacters(in: .whitespacesAndNewlines):一次性去掉字符串前后的所有空白字符(包括空格、换行符等),比手动判断空格更全面。addingPercentEncoding(withAllowedCharacters: .urlPathAllowed):系统会自动把ñ、é、空格等字符转换成URL合法格式(比如ñ→%C3%B1,é→%C3%A9),确保URL能被服务器正确识别。- 双重
guard let:分别处理编码失败和URL构建失败的情况,彻底避免因无效数据导致的崩溃。 - 补充
resume():原代码中网络任务未调用此方法,会导致请求根本不执行,已一并修复。
内容的提问来源于stack exchange,提问作者SirEdwardIII
相关产品推荐
相关产品推荐

