首页 > 解决方案 > 如何配置 SwiftUI openweathermap 应用程序以搜索包含多个单词的城市名称(例如纽约市)

问题描述

我正在构建一个使用 openweathermap API 的 SwiftUI 天气应用程序。我的应用程序当前配置为识别单字城市名称。但是,我还想配置应用程序以识别具有多个单词的城市名称(例如纽约市、洛杉矶......)。我不知道从哪里开始。是否有用于配置 API 密钥 URL 的协议来处理此问题?

https://api.openweathermap.org/data/2.5/weather?q=\(cityName)&units=imperial&appid=<myAPIKey>

还是需要在我的视图模型的其他地方以编程方式处理?

到目前为止,这是我的应用程序的代码,作为参考:

内容视图

import SwiftUI

struct ContentView: View {
    // Whenever something in the viewmodel changes, the content view will know to update the UI related elements
    @StateObject var viewModel = WeatherViewModel()
    @State private var cityName = ""
    
    var body: some View {
        NavigationView {
            VStack {
                TextField("Enter City Name", text: $cityName).textFieldStyle(.roundedBorder)
                Button(action: {
                    viewModel.fetchWeather(for: cityName)
                    cityName = ""
                }, label: {
                    Text("Search")
                        .padding(10)
                        .background(Color.green)
                        .foregroundColor(Color.white)
                        .cornerRadius(10)
                })
                List {
                    ForEach(viewModel.cityNameList) { city in
                        NavigationLink(destination: DetailView(detail: city)) {
                            HStack {
                                Text(city.name).font(.system(size: 32))
                            }
                        }
                    }
                }
                Spacer()
            }.navigationTitle("Weather MVVM")
        }.padding()
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

视图模型

import Foundation

class WeatherViewModel: ObservableObject {
    @Published var cityNameList = [WeatherModel]()

    func fetchWeather(for cityName: String) {
        guard let url = URL(string: "https://api.openweathermap.org/data/2.5/weather?q=\(cityName)&units=imperial&appid=<MyAPIKey>") 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.cityNameList.append(model)
                }
            }
            catch {
                print(error) // <-- you HAVE TO deal with errors here
            }
        }
        task.resume()
    }
}

模型

import Foundation

struct WeatherModel: Identifiable, Codable {
    let id = UUID()
    var name: String = ""
    var main: CurrentWeather = CurrentWeather()
    var weather: [WeatherInfo] = []
    
    func firstWeatherInfo() -> String {
        return weather.count > 0 ? weather[0].description : ""
    }
}

struct CurrentWeather: Codable {
    var temp: Float = 0.0
}

struct WeatherInfo: Codable {
    var description: String = ""
}

详细视图

import SwiftUI

struct DetailView: View {
    
    var detail: WeatherModel
    
    var body: some View {
        
        VStack(spacing: 20) {
            Text(detail.name)
                .font(.system(size: 32))
            Text("\(detail.main.temp)")
                .font(.system(size: 44))
            Text(detail.firstWeatherInfo())
                .font(.system(size: 24))
        }
        

    }
}

struct DetailView_Previews: PreviewProvider {
    static var previews: some View {
        DetailView(detail: WeatherModel.init())
    }
}

标签: iosswiftswiftuiswiftui-listopenweathermap

解决方案


推荐阅读