如何通过API OpenWeatherApi城市搜索



我创建了这些请求,我不知道我问得是否正确。如果有人能说出来,他们会感激的。这是我的密码。我需要在搜索中搜索一个城市,这样天气就会显示在表格中。请帮助并告诉我如何设置以及在哪里修复它。或者我设置的函数和方法不正确?错误

"数据丢失,无法读取">

import UIKit
class SearchViewController: UIViewController,UISearchResultsUpdating, UITableViewDelegate,UITableViewDataSource {


@IBOutlet weak var searchBar: UISearchBar!
@IBOutlet weak var tableView: UITableView!

var filteredCity: [OpenWeather] = []

// var searchCity: [OpenWeather]=[]
let wetherApi = WeatherManager()
var cityWeather = [OpenWeather]()
let netSer = NetworkService()
let searchController = UISearchController()

var isSearchBarEmpty: Bool {
return searchController.searchBar.text?.isEmpty ?? true
}


override func viewDidLoad() {
super.viewDidLoad()
searchController.searchResultsUpdater = self
navigationItem.searchController = searchController
tableView.delegate = self
tableView.dataSource = self
wetherApi.fetchCurrentWeather(city: "London")


}


func updateSearchResults(for searchController: UISearchController) {
self.filteredCity = self.cityWeather.filter { (city:OpenWeather) -> Bool in
if city.city.lowercased().contains(self.searchController.searchBar.text!.lowercased()){
return true
}else {
return false
}
}
//Update the results TableView
self.tableView.reloadData()
}


@objc func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cityWeather.count
}


@objc(tableView:cellForRowAtIndexPath:) internal func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CityTableViewCell

cell.cityTemp.text = cityWeather[indexPath.row].city
cell.cityTemp.text = "(cityWeather[indexPath.row].main.tempCelsius)"


return cell
}
}

我的结构天气:

import Foundation
import UIKit
struct OpenWeather: Codable  {
let coord:Coordinate
let city:String
let weathertwo:[WeatherTwo]
let main: Main


}
struct Coordinate: Codable {
let lan:Float
let lot:Float
enum CodingKeys: String, CodingKey  {
case lan = "lat"
case lot = "lon"
}
}
struct WeatherTwo: Codable {
let main: String
let description: String 
}
struct Main: Codable {
private let temp: Double
var tempCelsius: Double {
get {
return (temp - 32) / 1.8
}
}
private let temp_min: Double
var tempCelsiusmin: Double {
get {
return (temp - 32) / 1.8
}
}
private let temp_max: Double
var tempCelsiusmax: Double {
get {
return (temp - 32) / 1.8
}
}
let pressure: Int
let humidity: Int

}

我的代码Api可编码下载:

struct WeatherManager {
//Deliberately deleted "q=London" within the url, because it needs to be customizable with a different city


func fetchCurrentWeather(city: String){
let URL_API = "https://api.openweathermap.org/data/2.5/weather?q="
let CITY_ID = city
//let URL_API_KEY = "<api_key>"
let session = URLSession(configuration: .default)


let urlString = URL_API + CITY_ID + "&appid=cfe547d810fc4ad95e8f24187c6b08da"

guard let url = URL(string: urlString) else {
print("Error building URL")
return
}

let task = session.dataTask(with: url) { (data, response, error) in

DispatchQueue.main.async {
if let error = error {
print(error.localizedDescription)
return
}

guard let data = data, let response = response as? HTTPURLResponse else {
print("Invalid data or response")
return
}

do {
if response.statusCode == 200 {
let items = try JSONDecoder().decode(OpenWeather.self, from: data)
print(items)
} else {
print("Response wasn't 200. It was: " + "n(response.statusCode)")
}
} catch {
print(error.localizedDescription)
}
}

}
task.resume()



}

}

我看到了发生这种情况的几个原因。

如果你看看API给你的响应,你会发现:

  1. weathertwocity不存在于响应中,但它们存在于OpenWeather结构中。如果你不总是期望这些数据出现在中,你需要让它们成为可选的,或者通过重写init来提供默认值

  2. 查看响应中的coord对象

"coord": {
"lon": -0.1257,
"lat": 51.5085
}

将键的拼写与coord结构进行比较:

struct Coordinate: Codable {
let lan:Float
let long:Float
}

如果你想使用不同的变量名,你需要考虑使用CodingKeys

然而,我认为最简单的修复方法是将OpenWeather结构更改为:

struct OpenWeather: Codable {
let coord: Coordinate
let city: String?
let weathertwo: [WeatherTwo]?
let main: Main
}

并将coords固定为:

struct Coordinate: Codable {
let lat: Float
let lon: Float
}

应该消除错误并给你所需的数据,因为我可以看到控制台上打印的Open Weather API数据:

OpenWeather(coord: TestApp.Coordinate(lat: 25.2582, lon: 55.3047), city: nil, weathertwo: nil, main: TestApp.Main(temp: 300.38, temp_min: 299.31, temp_max: 301.29, pressure: 1008, humidity: 54))

还可以进行其他改进,例如使用CodingKeys对变量使用camel-case,但这是您稍后可以决定的。

试试这个,看看它是否能解决你的问题。

更新

正如你正确指出的,你问如何获得Open Weather支持的城市列表。

我快速看了一下,看起来他们没有API来获得所有城市的列表。他们的API似乎支持您发送城市名称,并将该城市的天气数据发送给您。

然而,他们在这里提供了他们的城市列表

我认为文件history.city.list.json.gz包含了所有的城市数据,如果你愿意,这些数据可能需要包含在你的应用程序或在线的某个地方。

看一看。

最新更新