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

Swift中如何从Tomorrow.io API仅提取温度数值数据

提取Tomorrow.io API返回的温度数值

我知道这是新手常遇到的问题,但它真的困扰着我!以下是我当前的Swift代码:

func WeatherAPI() async throws {
    let parameters = [
      "location": "Greenvale Victoria",
      "fields": ["temperature"],
      "units": "metric",
      "timesteps": ["1h"],
      "startTime": "2025-03-03T00:00:00+11:00",
      "endTime": "nowPlus24h",
      "dailyStartHour": 6,
      "timezone": "Australia/Melbourne"
    ] as [String : Any?]

    let postData = try JSONSerialization.data(withJSONObject: parameters, options: [])

    let url = URL(string: "https://api.tomorrow.io/v4/timelines")!
    var components = URLComponents(url: url, resolvingAgainstBaseURL: true)!
    let queryItems: [URLQueryItem] = [
      URLQueryItem(name: "apikey", value: "This ain't for you!"),
    ]
    components.queryItems = components.queryItems.map { $0 + queryItems } ?? queryItems

    var request = URLRequest(url: components.url!)
    request.httpMethod = "POST"
    request.timeoutInterval = 10
    request.allHTTPHeaderFields = [
      "accept": "application/json",
      "Accept-Encoding": "deflate, gzip, br",
      "content-type": "application/json"
    ]
    request.httpBody = postData

    let (data, temperature) = try await URLSession.shared.data(for: request)
    print(String(decoding: data, as: UTF8.self))
}

调用Tomorrow.io的/v4/timelines接口后,print返回了完整结构的JSON:

{"data":{"timelines":[{"timestep":"1h","endTime":"2025-03-04T13:00:00+11:00","startTime":"2025-03-03T00:00:00+11:00","intervals":[{"startTime":"2025-03-03T00:00:00+11:00","values":{"temperature":14.3}},{"startTime":"2025-03-03T01:00:00+11:00","values":{"temperature":13.9}},{"startTime":"2025-03-03T02:00:00+11:00","values":{"temperature":13.4}},{"startTime":"2025-03-03T03:00:00+11:00","values":{"temperature":13.1}},{"startTime":"2025-03-03T04:00:00+11:00","values":{"temperature":12.7}},{"startTime":"2025-03-03T05:00:00+11:00","values":{"temperature":12.5}},{"startTime":"2025-03-03T06:00:00+11:00","values":{"temperature":11.6}},{"startTime":"2025-03-03T07:00:00+11:00","values":{"temperature":11.3}},{"startTime":"2025-03-03T08:00:00+11:00","values":{"temperature":12.3}},{"startTime":"2025-03-03T09:00:00+11:00","values":{"temperature":14.4}},{"startTime":"2025-03-03T10:00:00+11:00","values":{"temperature":16.4}},{"startTime":"2025-03-03T11:00:00+11:00","values":{"temperature":17.6}},{"startTime":"2025-03-03T12:00:00+11:00","values":{"temperature":18.8}},{"startTime":"2025-03-03T13:00:00+11:00","values":{"temperature":19.7}},{"startTime":"2025-03-03T14:00:00+11:00","values":{"temperature":20.2}},{"startTime":"2025-03-03T15:00:00+11:00","values":{"temperature":20}},{"startTime":"2025-03-03T16:00:00+11:00","values":{"temperature":19.6}},{"startTime":"2025-03-03T17:00:00+11:00","values":{"temperature":19}},{"startTime":"2025-03-03T18:00:00+11:00","values":{"temperature":18.1}},{"startTime":"2025-03-03T19:00:00+11:00","values":{"temperature":17}},{"startTime":"2025-03-03T20:00:00+11:00","values":{"temperature":15.9}},{"startTime":"2025-03-03T21:00:00+11:00","values":{"temperature":15.3}},{"startTime":"2025-03-03T22:00:00+11:00","values":{"temperature":14.7}},{"startTime":"2025-03-03T23:00:00+11:00","values":{"temperature":14.2}},{"startTime":"2025-03-04T00:00:00+11:00","values":{"temperature":13.7}},{"startTime":"2025-03-04T01:00:00+11:00","values":{"temperature":13.3}},{"startTime":"2025-03-04T02:00:00+11:00","values":{"temperature":13.1}},{"startTime":"2025-03-04T03:00:00+11:00","values":{"temperature":12.7}},{"startTime":"2025-03-04T04:00:00+11:00","values":{"temperature":12.3}},{"startTime":"2025-03-04T05:00:00+11:00","values":{"temperature":11.9}},{"startTime":"2025-03-04T06:00:00+11:00","values":{"temperature":11.5}},{"startTime":"2025-03-04T07:00:00+11:00","values":{"temperature":11.2}},{"startTime":"2025-03-04T08:00:00+11:00","values":{"temperature":12.3}},{"startTime":"2025-03-04T09:00:00+11:00","values":{"temperature":14.9}},{"startTime":"2025-03-04T10:00:00+11:00","values":{"temperature":17.3}},{"startTime":"2025-03-04T11:00:00+11:00","values":{"temperature":20.6}},{"startTime":"2025-03-04T12:00:00+11:00","values":{"temperature":24.8}},{"startTime":"2025-03-04T13:00:00+11:00","values":{"temperature":28}}]}]}}

我只想要温度数值,希望能直接像这样访问:

// 示例
if let temperatures = extractedTemperatures {
    print(temperatures[0]) // 第一个温度值
    print(temperatures[1]) // 第二个温度值
    print(temperatures[2]) // 第三个温度值
}

解决方案

方法一:使用Codable(推荐,类型安全)

先定义对应JSON结构的Codable模型:

struct WeatherResponse: Codable {
    let data: WeatherData
}

struct WeatherData: Codable {
    let timelines: [Timeline]
}

struct Timeline: Codable {
    let intervals: [Interval]
}

struct Interval: Codable {
    let values: Values
}

struct Values: Codable {
    let temperature: Double
}

然后修改你的API函数,解析数据并提取温度数组:

func WeatherAPI() async throws -> [Double] {
    let parameters = [
        "location": "Greenvale Victoria",
        "fields": ["temperature"],
        "units": "metric",
        "timesteps": ["1h"],
        "startTime": "2025-03-03T00:00:00+11:00",
        "endTime": "nowPlus24h",
        "dailyStartHour": 6,
        "timezone": "Australia/Melbourne"
    ] as [String : Any] // 去掉Optional,避免JSONSerialization报错

    let postData = try JSONSerialization.data(withJSONObject: parameters, options: [])

    let url = URL(string: "https://api.tomorrow.io/v4/timelines")!
    var components = URLComponents(url: url, resolvingAgainstBaseURL: true)!
    components.queryItems = [URLQueryItem(name: "apikey", value: "This ain't for you!")]

    var request = URLRequest(url: components.url!)
    request.httpMethod = "POST"
    request.timeoutInterval = 10
    request.allHTTPHeaderFields = [
        "accept": "application/json",
        "Accept-Encoding": "deflate, gzip, br",
        "content-type": "application/json"
    ]
    request.httpBody = postData

    let (data, _) = try await URLSession.shared.data(for: request)
    let response = try JSONDecoder().decode(WeatherResponse.self, from: data)
    
    // 提取所有温度值
    let temperatures = response.data.timelines.flatMap { $0.intervals.map { $0.values.temperature } }
    return temperatures
}

调用方式:

Task {
    do {
        let temperatures = try await WeatherAPI()
        print(temperatures[0]) // 14.3
        print(temperatures[1]) // 13.9
        print(temperatures[2]) // 13.4
    } catch {
        print(error)
    }
}

方法二:使用JSONSerialization(快速实现,无类型安全)

如果不想定义模型,可以直接解析JSON提取温度:

func WeatherAPI() async throws -> [Double] {
    // ... 前面的请求代码和原来一致 ...
    
    let (data, _) = try await URLSession.shared.data(for: request)
    
    guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
          let dataDict = json["data"] as? [String: Any],
          let timelines = dataDict["timelines"] as? [[String: Any]],
          let firstTimeline = timelines.first,
          let intervals = firstTimeline["intervals"] as? [[String: Any]] else {
        throw NSError(domain: "ParseError", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to parse JSON"])
    }
    
    let temperatures = intervals.compactMap { interval in
        guard let values = interval["values"] as? [String: Double],
              let temp = values["temperature"] else { return nil }
        return temp
    }
    
    return temperatures
}

调用方式和方法一相同。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 01:52:01