我创建了这些请求,我不知道我问得对不对。如果有人能说出来,他们会感激的。这是我的密码。我需要在搜索中搜索一个城市,这样天气就会显示在桌子上。请帮助我,告诉我如何设置和修复它。还是我设置的函数和方法不正确?错误
“数据无法读取,因为数据丢失了。”
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()
}
}
发布于 2022-03-20 12:07:13
我看到了发生这种情况的几个原因。
如果您查看响应API给您,您会发现:
weathertwo
和city
,但它们存在于OpenWeather
结构中。如果不总是期望这些数据存在,则需要使它们成为可选的,或者通过重写init来提供默认值。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
}
并固定这方面的弦:
struct Coordinate: Codable {
let lat: Float
let lon: Float
}
应该消除错误,并提供您所需的数据,因为我可以看到控制台上打印的开放天气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))
还可以进行其他一些改进,比如使用camel对CodingKeys变量使用camel,但这是您以后可以决定的。
试一试,看看它是否能解决你的问题。
更新
正如您正确地指出的,您询问如何获得开放天气支持的城市列表。
我看了一眼,他们似乎没有一个API来获取所有城市的列表。他们的API似乎支持您发送城市名称,它将向您发送该城市的天气数据。
然而,他们提供了他们的这里的城市名单
我认为history.city.list.json.gz
文件包含了所有的城市数据,如果你愿意的话,这些数据可能需要包含在你的应用程序中或者在线的某个地方。
看一看。
https://stackoverflow.com/questions/71546338
复制相似问题