关于在用户查询后将数据从 API 传递到视图控制器的问题 - Swift
Question about passing data from an API into a view controller after user query - Swift
我正在不知疲倦地开发一个应用程序,但我对 Swift 还是个新手。我试图在用户在登录屏幕上输入后从 API 调用中获取数据,然后在显示用户想要的数据的模态弹出窗口上显示 API 调用的结果。这是一款航空气象应用;用户输入类似“KDAB”的内容和 API returns 该机场当前的航空天气。我为不同的值设置了一堆标签,可以在搜索后将它们打印到控制台,但似乎无法将它们打印在 VC 中。我尝试了一些 destination.segue 修复,但不明白我为什么要使用它们 - 数据直接来自解码 JSON。帮助将不胜感激!
我试图在每个值标签的 ReportViewController 上显示。 IE。使用 .text 属性.
的 windSpeedValueLabel 中的风速
现在,实际 ReportViewController 上的默认标签没有任何变化。
再次感谢。
我的代码:
//
// ReportViewController.swift
// AvWx Pro
//
// Created by Grayson Bertaina on 9/22/20.
//
import UIKit
class ReportViewController: UIViewController, WeatherManagerDelegate {
var weatherManager = WeatherManager()
@IBOutlet weak var flightRulesTitleLabel: UILabel!
@IBOutlet weak var flightRulesValueLabel: UILabel!
@IBOutlet weak var visibilityValueLabel: UILabel!
@IBOutlet weak var altimeterValueLabel: UILabel!
@IBOutlet weak var cloudsTitleLabel: UILabel!
@IBOutlet weak var cloudsType1Label: UILabel!
@IBOutlet weak var cloudsAltitude1Label: UILabel!
@IBOutlet weak var cloudsType2Label: UILabel!
@IBOutlet weak var cloudsAltitude2Label: UILabel!
@IBOutlet weak var cloudsType3Label: UILabel!
@IBOutlet weak var cloudsAltitude3Label: UILabel!
@IBOutlet weak var windGTextLabel: UILabel!
@IBOutlet weak var windSpeedValueLabel: UILabel!
@IBOutlet weak var windGustValueLabel: UILabel!
@IBOutlet weak var windFromTextLabel: UILabel!
@IBOutlet weak var windDirectionValueLabel: UILabel!
@IBOutlet weak var remarksValueLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel) {
DispatchQueue.main.async {
self.flightRulesValueLabel.text = weather.flightRules
self.cloudsType1Label.text = weather.lowestCloudsType
}
}
func didFailWithError(error: Error) {
print(error)
}
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
}
//
// ViewController.swift
// AvWx Pro
//
// Created by Grayson Bertaina on 9/21/20.
//
import UIKit
class WxViewController: UIViewController, UITextFieldDelegate, WeatherManagerDelegate {
var weatherManager = WeatherManager()
@IBOutlet weak var stationSearch: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
weatherManager.delegate = self
stationSearch.delegate = self
}
@IBAction func searchPressed(_ sender: Any) {
print(stationSearch.text!)
stationSearch.endEditing(true)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
print(stationSearch.text!)
stationSearch.endEditing(true)
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
if let station = stationSearch.text {
weatherManager.fetchWeather(stationICAO: station)
}
stationSearch.text = ""
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
if stationSearch.text != "" {
return true
} else {
stationSearch.placeholder = "Type an ICAO"
return false
}
}
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel) {
print(weather.flightConditions)
}
func didFailWithError(error: Error) {
print(error)
}
}
//
// WeatherManager.swift
// AvWx Pro
//
// Created by Grayson Bertaina on 9/21/20.
//
import Foundation
protocol WeatherManagerDelegate {
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel)
func didFailWithError(error: Error)
}
struct WeatherManager {
let weatherURL = "https://avwx.rest/api/metar/"
var delegate : WeatherManagerDelegate?
func fetchWeather (stationICAO: String) {
let urlString = "\(weatherURL)\(stationICAO)?token=OVi45FiTDo1LmyodShfOfoizNe5m9wyuO6Mkc95AN-c"
performRequest(with: urlString)
}
func performRequest (with urlString: String) {
if let url = URL(string: urlString) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil {
self.delegate?.didFailWithError(error: error!)
return
}
if let safeData = data {
if let weather = self.parseJSON(safeData) {
self.delegate?.didUpdateWeather(self, weather: weather)
}
}
}
task.resume()
print(urlString)
}
}
func parseJSON(_ weatherData: Data) -> WeatherModel? {
do {
let decoder = JSONDecoder()
let decodedData = try decoder.decode(WeatherData.self, from: weatherData)
let clouds = decodedData.clouds
let lowCloudsType = (clouds.count > 0 ? clouds[0]?.type : nil) ?? "N/A"
let midCloudsType = (clouds.count > 1 ? clouds[1]?.type : nil) ?? "N/A"
let highCloudsType = (clouds.count > 2 ? clouds[2]?.type : nil) ?? "N/A"
let lowCloudsAlt = (clouds.count > 0 ? clouds[0]?.altitude : nil) ?? 0
let midCloudsAlt = (clouds.count > 1 ? clouds[1]?.altitude : nil) ?? 0
let highCloudsAlt = (clouds.count > 2 ? clouds[2]?.altitude : nil) ?? 0
let reportingStationVar = decodedData.station ?? "N/A"
let windGustValue = decodedData.wind_gust?.value ?? 0
let windSpeedValue = decodedData.wind_speed?.value ?? 0
let windDirectionValue = decodedData.wind_direction?.value ?? 999
let visibilityValue = decodedData.visibility?.value ?? 0
let flightRulesValue = decodedData.flight_rules ?? "N/A"
let weather = WeatherModel(lowestCloudsType: lowCloudsType , lowestCloudsAlt: lowCloudsAlt, middleCloudsType: midCloudsType , middleCloudsAlt: midCloudsAlt, highestCloudsType: highCloudsType , highestCloudsAlt: highCloudsAlt, reportingStation: reportingStationVar, windGust: windGustValue, windSpeed: windSpeedValue, windDirection: windDirectionValue, visibility: visibilityValue, flightRules: flightRulesValue)
return weather
} catch {
delegate?.didFailWithError(error: error)
return nil
}
}
}
//
// WeatherData.swift
// AvWx Pro
//
// Created by Grayson Bertaina on 9/21/20.
//
import Foundation
struct WeatherData: Codable {
let clouds: [Clouds?]
let flight_rules: String?
let remarks: String?
let wind_speed: WindSpeed?
let wind_gust: WindGust?
let wind_direction: WindDirection?
let visibility: Visibility?
let station: String?
}
struct Clouds: Codable {
let type: String
let altitude: Int
}
struct WindSpeed: Codable {
let value: Int
}
struct WindGust: Codable {
let value: Int
}
struct WindDirection: Codable {
let value: Int
}
struct Visibility: Codable {
let value: Int
}
再次感谢。
首先,在 WeatherManager 上,将您的委托声明为弱委托以避免引用循环
weak var delegate : WeatherManagerDelegate?
其次,解码数据后,您必须调用委托并传递数据,在本例中,是您刚刚使用委托方法之一创建的 WeatherModel
do {
let decoder = JSONDecoder()
let decodedData = try decoder.decode(WeatherData.self, from: weatherData)
let clouds = decodedData.clouds
let lowCloudsType = (clouds.count > 0 ? clouds[0]?.type : nil) ?? "N/A"
let midCloudsType = (clouds.count > 1 ? clouds[1]?.type : nil) ?? "N/A"
let highCloudsType = (clouds.count > 2 ? clouds[2]?.type : nil) ?? "N/A"
let lowCloudsAlt = (clouds.count > 0 ? clouds[0]?.altitude : nil) ?? 0
let midCloudsAlt = (clouds.count > 1 ? clouds[1]?.altitude : nil) ?? 0
let highCloudsAlt = (clouds.count > 2 ? clouds[2]?.altitude : nil) ?? 0
let reportingStationVar = decodedData.station ?? "N/A"
let windGustValue = decodedData.wind_gust?.value ?? 0
let windSpeedValue = decodedData.wind_speed?.value ?? 0
let windDirectionValue = decodedData.wind_direction?.value ?? 999
let visibilityValue = decodedData.visibility?.value ?? 0
let flightRulesValue = decodedData.flight_rules ?? "N/A"
let weather = WeatherModel(lowestCloudsType: lowCloudsType , lowestCloudsAlt: lowCloudsAlt, middleCloudsType: midCloudsType , middleCloudsAlt: midCloudsAlt, highestCloudsType: highCloudsType , highestCloudsAlt: highCloudsAlt, reportingStation: reportingStationVar, windGust: windGustValue, windSpeed: windSpeedValue, windDirection: windDirectionValue, visibility: visibilityValue, flightRules: flightRulesValue)
delegate?.didUpdateWeather(self, weather: weather)
return weather
} catch {
delegate?.didFailWithError(error: error)
return nil
}
在 ReportViewController 上,将自己指定为 viewDidLoad() 上的 WeatherManagerDelegate,然后您必须通过使用相应的值更新标签来实现委托函数 didUpdateWeather——您已经开始了
class ReportViewController: UIViewController, WeatherManagerDelegate {
var weatherManager = WeatherManager()
@IBOutlet weak var flightRulesTitleLabel: UILabel!
@IBOutlet weak var flightRulesValueLabel: UILabel!
@IBOutlet weak var visibilityValueLabel: UILabel!
@IBOutlet weak var altimeterValueLabel: UILabel!
@IBOutlet weak var cloudsTitleLabel: UILabel!
@IBOutlet weak var cloudsType1Label: UILabel!
@IBOutlet weak var cloudsAltitude1Label: UILabel!
@IBOutlet weak var cloudsType2Label: UILabel!
@IBOutlet weak var cloudsAltitude2Label: UILabel!
@IBOutlet weak var cloudsType3Label: UILabel!
@IBOutlet weak var cloudsAltitude3Label: UILabel!
@IBOutlet weak var windGTextLabel: UILabel!
@IBOutlet weak var windSpeedValueLabel: UILabel!
@IBOutlet weak var windGustValueLabel: UILabel!
@IBOutlet weak var windFromTextLabel: UILabel!
@IBOutlet weak var windDirectionValueLabel: UILabel!
@IBOutlet weak var remarksValueLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
weatherManager.delegate = self
}
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel) {
DispatchQueue.main.async {
self.flightRulesValueLabel.text = weather.flightRules
self.cloudsType1Label.text = weather.lowestCloudsType
}
}
我正在不知疲倦地开发一个应用程序,但我对 Swift 还是个新手。我试图在用户在登录屏幕上输入后从 API 调用中获取数据,然后在显示用户想要的数据的模态弹出窗口上显示 API 调用的结果。这是一款航空气象应用;用户输入类似“KDAB”的内容和 API returns 该机场当前的航空天气。我为不同的值设置了一堆标签,可以在搜索后将它们打印到控制台,但似乎无法将它们打印在 VC 中。我尝试了一些 destination.segue 修复,但不明白我为什么要使用它们 - 数据直接来自解码 JSON。帮助将不胜感激!
我试图在每个值标签的 ReportViewController 上显示。 IE。使用 .text 属性.
的 windSpeedValueLabel 中的风速现在,实际 ReportViewController 上的默认标签没有任何变化。
再次感谢。
我的代码:
//
// ReportViewController.swift
// AvWx Pro
//
// Created by Grayson Bertaina on 9/22/20.
//
import UIKit
class ReportViewController: UIViewController, WeatherManagerDelegate {
var weatherManager = WeatherManager()
@IBOutlet weak var flightRulesTitleLabel: UILabel!
@IBOutlet weak var flightRulesValueLabel: UILabel!
@IBOutlet weak var visibilityValueLabel: UILabel!
@IBOutlet weak var altimeterValueLabel: UILabel!
@IBOutlet weak var cloudsTitleLabel: UILabel!
@IBOutlet weak var cloudsType1Label: UILabel!
@IBOutlet weak var cloudsAltitude1Label: UILabel!
@IBOutlet weak var cloudsType2Label: UILabel!
@IBOutlet weak var cloudsAltitude2Label: UILabel!
@IBOutlet weak var cloudsType3Label: UILabel!
@IBOutlet weak var cloudsAltitude3Label: UILabel!
@IBOutlet weak var windGTextLabel: UILabel!
@IBOutlet weak var windSpeedValueLabel: UILabel!
@IBOutlet weak var windGustValueLabel: UILabel!
@IBOutlet weak var windFromTextLabel: UILabel!
@IBOutlet weak var windDirectionValueLabel: UILabel!
@IBOutlet weak var remarksValueLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel) {
DispatchQueue.main.async {
self.flightRulesValueLabel.text = weather.flightRules
self.cloudsType1Label.text = weather.lowestCloudsType
}
}
func didFailWithError(error: Error) {
print(error)
}
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
}
//
// ViewController.swift
// AvWx Pro
//
// Created by Grayson Bertaina on 9/21/20.
//
import UIKit
class WxViewController: UIViewController, UITextFieldDelegate, WeatherManagerDelegate {
var weatherManager = WeatherManager()
@IBOutlet weak var stationSearch: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
weatherManager.delegate = self
stationSearch.delegate = self
}
@IBAction func searchPressed(_ sender: Any) {
print(stationSearch.text!)
stationSearch.endEditing(true)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
print(stationSearch.text!)
stationSearch.endEditing(true)
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
if let station = stationSearch.text {
weatherManager.fetchWeather(stationICAO: station)
}
stationSearch.text = ""
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
if stationSearch.text != "" {
return true
} else {
stationSearch.placeholder = "Type an ICAO"
return false
}
}
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel) {
print(weather.flightConditions)
}
func didFailWithError(error: Error) {
print(error)
}
}
//
// WeatherManager.swift
// AvWx Pro
//
// Created by Grayson Bertaina on 9/21/20.
//
import Foundation
protocol WeatherManagerDelegate {
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel)
func didFailWithError(error: Error)
}
struct WeatherManager {
let weatherURL = "https://avwx.rest/api/metar/"
var delegate : WeatherManagerDelegate?
func fetchWeather (stationICAO: String) {
let urlString = "\(weatherURL)\(stationICAO)?token=OVi45FiTDo1LmyodShfOfoizNe5m9wyuO6Mkc95AN-c"
performRequest(with: urlString)
}
func performRequest (with urlString: String) {
if let url = URL(string: urlString) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil {
self.delegate?.didFailWithError(error: error!)
return
}
if let safeData = data {
if let weather = self.parseJSON(safeData) {
self.delegate?.didUpdateWeather(self, weather: weather)
}
}
}
task.resume()
print(urlString)
}
}
func parseJSON(_ weatherData: Data) -> WeatherModel? {
do {
let decoder = JSONDecoder()
let decodedData = try decoder.decode(WeatherData.self, from: weatherData)
let clouds = decodedData.clouds
let lowCloudsType = (clouds.count > 0 ? clouds[0]?.type : nil) ?? "N/A"
let midCloudsType = (clouds.count > 1 ? clouds[1]?.type : nil) ?? "N/A"
let highCloudsType = (clouds.count > 2 ? clouds[2]?.type : nil) ?? "N/A"
let lowCloudsAlt = (clouds.count > 0 ? clouds[0]?.altitude : nil) ?? 0
let midCloudsAlt = (clouds.count > 1 ? clouds[1]?.altitude : nil) ?? 0
let highCloudsAlt = (clouds.count > 2 ? clouds[2]?.altitude : nil) ?? 0
let reportingStationVar = decodedData.station ?? "N/A"
let windGustValue = decodedData.wind_gust?.value ?? 0
let windSpeedValue = decodedData.wind_speed?.value ?? 0
let windDirectionValue = decodedData.wind_direction?.value ?? 999
let visibilityValue = decodedData.visibility?.value ?? 0
let flightRulesValue = decodedData.flight_rules ?? "N/A"
let weather = WeatherModel(lowestCloudsType: lowCloudsType , lowestCloudsAlt: lowCloudsAlt, middleCloudsType: midCloudsType , middleCloudsAlt: midCloudsAlt, highestCloudsType: highCloudsType , highestCloudsAlt: highCloudsAlt, reportingStation: reportingStationVar, windGust: windGustValue, windSpeed: windSpeedValue, windDirection: windDirectionValue, visibility: visibilityValue, flightRules: flightRulesValue)
return weather
} catch {
delegate?.didFailWithError(error: error)
return nil
}
}
}
//
// WeatherData.swift
// AvWx Pro
//
// Created by Grayson Bertaina on 9/21/20.
//
import Foundation
struct WeatherData: Codable {
let clouds: [Clouds?]
let flight_rules: String?
let remarks: String?
let wind_speed: WindSpeed?
let wind_gust: WindGust?
let wind_direction: WindDirection?
let visibility: Visibility?
let station: String?
}
struct Clouds: Codable {
let type: String
let altitude: Int
}
struct WindSpeed: Codable {
let value: Int
}
struct WindGust: Codable {
let value: Int
}
struct WindDirection: Codable {
let value: Int
}
struct Visibility: Codable {
let value: Int
}
再次感谢。
首先,在 WeatherManager 上,将您的委托声明为弱委托以避免引用循环
weak var delegate : WeatherManagerDelegate?
其次,解码数据后,您必须调用委托并传递数据,在本例中,是您刚刚使用委托方法之一创建的 WeatherModel
do {
let decoder = JSONDecoder()
let decodedData = try decoder.decode(WeatherData.self, from: weatherData)
let clouds = decodedData.clouds
let lowCloudsType = (clouds.count > 0 ? clouds[0]?.type : nil) ?? "N/A"
let midCloudsType = (clouds.count > 1 ? clouds[1]?.type : nil) ?? "N/A"
let highCloudsType = (clouds.count > 2 ? clouds[2]?.type : nil) ?? "N/A"
let lowCloudsAlt = (clouds.count > 0 ? clouds[0]?.altitude : nil) ?? 0
let midCloudsAlt = (clouds.count > 1 ? clouds[1]?.altitude : nil) ?? 0
let highCloudsAlt = (clouds.count > 2 ? clouds[2]?.altitude : nil) ?? 0
let reportingStationVar = decodedData.station ?? "N/A"
let windGustValue = decodedData.wind_gust?.value ?? 0
let windSpeedValue = decodedData.wind_speed?.value ?? 0
let windDirectionValue = decodedData.wind_direction?.value ?? 999
let visibilityValue = decodedData.visibility?.value ?? 0
let flightRulesValue = decodedData.flight_rules ?? "N/A"
let weather = WeatherModel(lowestCloudsType: lowCloudsType , lowestCloudsAlt: lowCloudsAlt, middleCloudsType: midCloudsType , middleCloudsAlt: midCloudsAlt, highestCloudsType: highCloudsType , highestCloudsAlt: highCloudsAlt, reportingStation: reportingStationVar, windGust: windGustValue, windSpeed: windSpeedValue, windDirection: windDirectionValue, visibility: visibilityValue, flightRules: flightRulesValue)
delegate?.didUpdateWeather(self, weather: weather)
return weather
} catch {
delegate?.didFailWithError(error: error)
return nil
}
在 ReportViewController 上,将自己指定为 viewDidLoad() 上的 WeatherManagerDelegate,然后您必须通过使用相应的值更新标签来实现委托函数 didUpdateWeather——您已经开始了
class ReportViewController: UIViewController, WeatherManagerDelegate {
var weatherManager = WeatherManager()
@IBOutlet weak var flightRulesTitleLabel: UILabel!
@IBOutlet weak var flightRulesValueLabel: UILabel!
@IBOutlet weak var visibilityValueLabel: UILabel!
@IBOutlet weak var altimeterValueLabel: UILabel!
@IBOutlet weak var cloudsTitleLabel: UILabel!
@IBOutlet weak var cloudsType1Label: UILabel!
@IBOutlet weak var cloudsAltitude1Label: UILabel!
@IBOutlet weak var cloudsType2Label: UILabel!
@IBOutlet weak var cloudsAltitude2Label: UILabel!
@IBOutlet weak var cloudsType3Label: UILabel!
@IBOutlet weak var cloudsAltitude3Label: UILabel!
@IBOutlet weak var windGTextLabel: UILabel!
@IBOutlet weak var windSpeedValueLabel: UILabel!
@IBOutlet weak var windGustValueLabel: UILabel!
@IBOutlet weak var windFromTextLabel: UILabel!
@IBOutlet weak var windDirectionValueLabel: UILabel!
@IBOutlet weak var remarksValueLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
weatherManager.delegate = self
}
func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel) {
DispatchQueue.main.async {
self.flightRulesValueLabel.text = weather.flightRules
self.cloudsType1Label.text = weather.lowestCloudsType
}
}