SwiftUI天气APP如何将输入值传入URL参数,WeatherModel占位值怎么设置?
问题解答
问题1:直接在viewModel中将searchCity.name传入URL的做法是否正确?
- 功能可跑但不符合规范,存在两个明显问题:
- 不必要的封装:你完全可以直接使用
enterCityName拼接到URL中,不需要额外创建WeatherModel实例中转,属于无效冗余操作 - 存在安全隐患:直接字符串拼接URL没有处理特殊字符,当城市名包含空格、中文、特殊符号(比如
New York、里约热内卢)时,会直接导致URL生成失败,请求报错。正确做法是用URLComponents构造请求,系统会自动对参数做百分号编码,兼容性更强。
- 不必要的封装:你完全可以直接使用
问题2:占位值的实现方式是否合理?
- 完全不合理:
- 职责错配:
WeatherModel的定位是解析接口返回数据的响应模型,不应该被用作请求参数的载体,两者的职责完全拆分 - 冗余无意义:你创建这个实例仅为了取name字段,其他两个属性的占位值没有任何作用,只会增加代码的理解成本,后续维护人员很容易搞不清这个临时实例的作用
- 职责错配:
优化后的代码参考
仅需要修改ViewModel中的fetchWeather方法即可,删掉不必要的临时WeatherModel创建逻辑,改用URLComponents构造安全的请求链接:
func fetchWeather() { // 先判断输入的城市名不为空 guard !enterCityName.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { return } // 用URLComponents构造请求,自动处理参数编码 var components = URLComponents(string: "https://api.openweathermap.org/data/2.5/weather") components?.queryItems = [ URLQueryItem(name: "q", value: enterCityName), URLQueryItem(name: "units", value: "imperial"), URLQueryItem(name: "appid", value: "<myAPIKey>") ] guard let url = components?.url else { return } // 后面的网络请求逻辑保持不变即可 let task = URLSession.shared.dataTask(with: url) { data, _, error in guard let data = data, error == nil else { return } do { let model = try JSONDecoder().decode(WeatherModel.self, from: data) DispatchQueue.main.async { self.title = model.name self.temp = "\(model.main.temp)" self.descriptionText = model.weather.first?.description ?? "No Description" } } catch { print(error) // 可选:请求失败时给UI做错误提示 DispatchQueue.main.async { self.title = "查询失败" self.temp = "-" self.descriptionText = "请检查城市名是否正确" } } } task.resume() }
内容的提问来源于stack exchange,提问作者JS_is_awesome18
相关产品推荐
相关产品推荐

