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

SwiftUI结合Combine调用OpenWeather无返回且报初始化不匹配错误

问题根因

  1. 接口返回格式匹配错误:OpenWeather对应接口返回的是单个JSON对象,你当前设置的解码类型为[WeatherDataModel].self(对象数组),类型不匹配直接导致解码失败,由于你没有捕获错误所以看不到具体报错。
  2. 命名冲突导致初始化报错:你定义了全局typealias weatherData = [WeatherDataModel],又在View中用@StateObject var weatherData = DownloadWeatherData(),变量名和类型别名重名,编译器无法识别类型,就会报No exact matches in call to initializer错误。

修复方案

1. 修正网络请求类的解码逻辑和属性类型

OpenWeather返回的是单个天气对象,不需要用数组接收,同时添加错误打印方便调试:

class DownloadWeatherData: ObservableObject {
    // 改成可选单个对象,不要数组
    @Published var weatherdata: WeatherDataModel?
    var weatherCancellabes = Set<AnyCancellable>()

    init() {
        print("loading weather init")
        getWeather(weatherUrl: "<my url>")
    }

    func getWeather(weatherUrl: String) {
        guard let weatherUrl = URL(string: weatherUrl) else { return }

        URLSession.shared.dataTaskPublisher(for: weatherUrl)
            .subscribe(on: DispatchQueue.global(qos: .background))
            .receive(on: DispatchQueue.main)
            .tryMap { (data, response) -> Data in
                guard let response = response as? HTTPURLResponse,
                      response.statusCode >= 200 && response.statusCode < 300 else {
                    throw URLError(.badServerResponse)
                }
                // 可选:打印返回的JSON字符串方便排查字段问题
                if let jsonStr = String(data: data, encoding: .utf8) {
                    print("返回JSON:\n\(jsonStr)")
                }
                return data
            }
            // 解码类型改为单个WeatherDataModel,不是数组
            .decode(type: WeatherDataModel.self, decoder: JSONDecoder())
            .sink { completion in
                // 添加错误捕获,解码失败会直接打印原因
                if case .failure(let error) = completion {
                    print("请求/解码失败: \(error)")
                }
            } receiveValue: { [weak self] returnedWeatherData in
                self?.weatherdata = returnedWeatherData
                print("解码成功: \(returnedWeatherData)")
            }
            .store(in: &weatherCancellabes)
    }
}

2. 修正View层的命名和渲染逻辑

修改变量名避免和全局typealias冲突,适配单个对象的渲染逻辑:

struct WeatherView: View {
    // 变量名改个不冲突的,比如weatherVM
    @StateObject var weatherVM = DownloadWeatherData()

    var body: some View {
        VStack {
            if let weather = weatherVM.weatherdata {
                Text("时区:\(weather.timezone)")
                Text("当前温度:\(weather.current.temp)")
                // 遍历daily字段显示每日天气
                ForEach(weather.daily, id: \.dt) { day in
                    Text("日期时间戳:\(day.dt) 最高温:\(day.temp.max)")
                }
            } else {
                Text("天气数据加载中...")
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 03:27:01