首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何通过API OpenWeatherApi城市搜索?

如何通过API OpenWeatherApi城市搜索?
EN

Stack Overflow用户
提问于 2022-03-20 11:29:06
回答 1查看 508关注 0票数 0

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

“数据无法读取,因为数据丢失了。”

代码语言:javascript
运行
复制
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
    }
}

我的结构天气:

代码语言:javascript
运行
复制
  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可编码下载:

代码语言:javascript
运行
复制
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()
        
        
        
    }
    
}
EN

回答 1

Stack Overflow用户

发布于 2022-03-20 12:07:13

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

如果您查看响应API给您,您会发现:

  1. 响应中不存在键weathertwocity,但它们存在于OpenWeather结构中。如果不总是期望这些数据存在,则需要使它们成为可选的,或者通过重写init来提供默认值。
  2. 查看响应中的coord对象
代码语言:javascript
运行
复制
"coord": {
"lon": -0.1257,
"lat": 51.5085
}

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

代码语言:javascript
运行
复制
struct Coordinate: Codable {
    let lan:Float
    let long:Float
}

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

但是,我认为最简单的解决方法是将OpenWeather结构更改为:

代码语言:javascript
运行
复制
struct OpenWeather: Codable {
    let coord: Coordinate
    let city: String?
    let weathertwo: [WeatherTwo]?
    let main: Main
}

并固定这方面的弦:

代码语言:javascript
运行
复制
struct Coordinate: Codable {
    let lat: Float
    let lon: Float
}

应该消除错误,并提供您所需的数据,因为我可以看到控制台上打印的开放天气API中的数据:

代码语言:javascript
运行
复制
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文件包含了所有的城市数据,如果你愿意的话,这些数据可能需要包含在你的应用程序中或者在线的某个地方。

看一看。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71546338

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档