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

如何在模型属性含API经纬度计算城市名时完成属性填充?

天气APP获取城市名的问题与解决方法

我正在开发一款简易天气APP,需展示用户城市名(此部分遇到问题)、当前温度、每日最高/最低温、风速、湿度。OpenWeatherMap API提供了除城市名外的所有数据,我难以梳理获取城市名的逻辑流程。

失败尝试

  • 创建包含天气报告所有属性的WeatherReport模型,其中city为可选属性,需通过逆地理编码(经纬度转地名)计算得到。
  • 通过.task从API下载数据并解码到模型(此步骤正常工作)。
  • 填充city属性的两次失败尝试:
    • 尝试1:为lat、lon添加didSet属性观察器调用reverseGeocode函数,但因多变量var声明不能有显式getter/setter失败。
    • 尝试2:修改reverseGeocode返回WeatherReport,但因未将其视为异步函数,导致时序问题,视图卡在加载状态。

最终解决方案

将reverseGeocode改为异步函数,使用async await处理,解决了数据填充的时序问题,代码如下:

func getCurrentWeather(latitude: CLLocationDegrees, longitude: CLLocationDegrees) async throws -> WeatherReport? {
        do {
            guard let url = URL(string: "https://api.openweathermap.org/data/3.0/onecall?lat=\(latitude)&lon=\(longitude)&exclude=current,minutely,hourly, alerts&appid=19054ace743dfdfd9&units=imperial") else { throw NetworkError.badURL}
            
            let (data, response) = try await URLSession.shared.data(from: url)
            
            guard let response = response as? HTTPURLResponse else { throw NetworkError.badResponse }
            guard response.statusCode >= 200 && response.statusCode < 300 else { throw NetworkError.badStatus }
            
            let decodedData = try JSONDecoder().decode(WeatherReport.self, from: data)
            let decodedDataWithCity = try await decodedData.reverseGeocode()
            return decodedDataWithCity
            
        } catch NetworkError.badURL {
            print("Error creating URL")
        } catch NetworkError.badResponse {
            print("Didn't get a valid response")
        } catch NetworkError.badStatus {
            print("Didn't get a 2xx status code from response")
        } catch {
            print("An error occurred downloading the data")
        }
        
        return nil
    }
func reverseGeocode() async throws -> WeatherReport? {
        let geocoder = CLGeocoder()
        let location = CLLocation(latitude: lat, longitude: lon)
        var report: WeatherReport?
        
        do {
            let placemarks = try await geocoder.reverseGeocodeLocation(location)
            let placemark = placemarks.first
            report = WeatherReport(lat: lat, lon: lon, city: placemark?.locality, timezone: timezone, timezoneOffset: timezoneOffset, daily: daily)
        } catch {
            print("Error: \(error.localizedDescription)")
        }
        
        return report
    }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 14:14:53