我正在开发一个应用程序,该应用程序从coindesks API获取信息,该信息会响应JSON,然后进行解析,并显示当前的比特币价格指数,图表名称等。我创建了NetworkingManager单例类,在其中进行GET要求使用AlamoFire吊舱,一切正常,这是NetworkingManager代码:
static let shared = NetworkManager()
let baseURL = "https://api.coindesk.com/v1/bpi/currentprice.json"
var btcEUR : String = ""
var btcGBP : String = ""
var btcUSD : String = ""
var eurSymbol : String = ""
var gbpSymbol : String = ""
var usdSymbol : String = ""
var chartName : String = ""
var timeUpdated : String = ""
private init() {
getBitcoinData(url: baseURL)
}
func getBitcoinData(url: String) {
Alamofire.request(url, method: .get)
.responseJSON { response in
if response.result.isSuccess {
print("Sucess! Got the bitcoin price data")
let responseJSON : JSON = JSON(response.result.value!)
self.updateBitcoinData(bitcoinJSON : responseJSON)
}
else{
print("Error \(String(describing: response.result.error))")
}
}
}
func updateBitcoinData(bitcoinJSON: JSON){
print("Parsing the JSON")
self.btcUSD = bitcoinJSON["bpi"]["USD"]["rate"].string!
self.btcGBP = bitcoinJSON["bpi"]["GBP"]["rate"].string!
self.btcEUR = bitcoinJSON["bpi"]["EUR"]["rate"].string!
self.usdSymbol = bitcoinJSON["bpi"]["USD"]["symbol"].string!.html2String
self.gbpSymbol = bitcoinJSON["bpi"]["GBP"]["symbol"].string!.html2String
self.eurSymbol = bitcoinJSON["bpi"]["EUR"]["symbol"].string!.html2String
self.chartName = bitcoinJSON["chartName"].string!
self.timeUpdated = self.convertUTCDateToLocalDate(dateToConvert: bitcoinJSON["time"]["updated"].string!)
print("JSON finished parsing")
}
func convertUTCDateToLocalDate(dateToConvert:String) -> String {
let format = DateFormatter()
format.dateFormat = "MMM dd, yyyy HH:mm:ss Z"
let convertedDate = format.date(from: dateToConvert)
format.timeZone = TimeZone.current
format.dateFormat = "MMM dd, yyyy HH:mm:ss ZZZZZ"
let localDateStr = format.string(from: convertedDate!)
return localDateStr
}
func getEurBTC() -> String {
return btcEUR
}
func getGbpBTC() -> String {
return btcGBP
}
func getUsdBTC() -> String {
return btcUSD
}
func getEurSymbol() -> String {
return eurSymbol
}
func getGbpSymbol() -> String {
return gbpSymbol
}
func getUsdSymbol() -> String {
return usdSymbol
}
func getChartName() -> String {
return chartName
}
func getTimeUpdated() -> String {
return timeUpdated
}
我遇到的问题是,在VC类中启动时,我希望该应用程序已经向用户显示比特币价格,chartName等。但是,如果我尝试在viewDidLoad中添加updateBitcoinData()函数或viewWillLoad,在启动时它们似乎是空字符串,好像NetworkingManager类无法完成其工作并且未将解析的JSON值分配给所需的变量一样,但是,如果我开始使用pickerView,它将开始显示解析的数据。
以下是显示我的问题的GIF:https://giphy.com/gifs/7Tf2jALO7YF6eE8jCA。
这是VC类:
let NetworkingHelper = NetworkManager.shared
let currencyArray = ["USD", "GBP", "EUR" ]
var currencySelected = ""
var USDBTC: String = ""
var GBPBTC: String = ""
var EURBTC: String = ""
var chart : String = ""
var time : String = ""
//Pre-setup IBOutlets
@IBOutlet weak var bitcoinPriceLabel: UILabel!
@IBOutlet weak var currencyPicker: UIPickerView!
@IBOutlet weak var chartName: UILabel!
@IBOutlet weak var timeUpdated: UILabel!
@IBAction func exchangeButtonPressed(_ sender: Any) {
let main = UIStoryboard(name: "Main", bundle: nil)
let calculatorvc = main.instantiateViewController(withIdentifier: "SecondVC")
self.present(calculatorvc,animated: true, completion: nil)
}
override func viewWillAppear(_ animated: Bool) {
updateBitcoinData()
}
override func viewDidLoad() {
super.viewDidLoad()
currencyPicker.delegate = self
currencyPicker.dataSource = self
}
//MARK: - Pickerview
/***************************************************************/
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
currencySelected = currencyArray[row]
let myTitle = NSAttributedString(string: currencySelected, attributes: [NSAttributedString.Key.foregroundColor: UIColor.white])
return myTitle
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return currencyArray.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return currencyArray[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
currencySelected = currencyArray[row]
updateBitcoinData()
switch currencySelected {
case "USD":
bitcoinPriceLabel.text = USDBTC
case "GBP":
bitcoinPriceLabel.text = GBPBTC
case "EUR":
bitcoinPriceLabel.text = EURBTC
default:
bitcoinPriceLabel.text = USDBTC
}
}
//MARK: - Assigning the view
/***************************************************************/
func updateBitcoinData() {
bitcoinPriceLabel.text = NetworkManager.shared.getUsdSymbol() + NetworkManager.shared.getUsdBTC()
chartName.text = NetworkManager.shared.getChartName()
timeUpdated.text = NetworkManager.shared.getTimeUpdated()
USDBTC = NetworkManager.shared.getUsdSymbol() + NetworkManager.shared.getUsdBTC()
GBPBTC = NetworkManager.shared.getGbpSymbol() + NetworkManager.shared.getGbpBTC()
EURBTC = NetworkManager.shared.getEurSymbol() + NetworkManager.shared.getEurBTC()
}
答案 0 :(得分:0)
似乎在您要更新标签时您的数据不存在。在print("something")
中插入另一个updateBitcoinData()
,看看它是否在Alamofire请求中的打印之前被调用。
最简单的解决方案是为ViewController注册一个自定义Notification
,该自定义class YourViewController: UIViewController {
// ...
deinit() {
NotificationCenter.default.removeObserver(self)
}
// ...
override func viewDidLoad() {
// ...
NotificationCenter.default.addObserver(self, selector: #selector(bitcoinDataReceived(_:)), name: NSNotification.Name(rawValue: "ReceivedBitcoinData"), object: nil)
// ...
}
// ...
@objc func bitcoinDataReceived(_ notification: Notification) {
updateBitcoinData()
}
}
在请求的响应返回数据时由NetworkManager发出。您还可以编写带有完成处理程序的函数,该函数在接收到数据时被调用。
通知解决方案
在您的ViewController类中实现:
class NetworkManager {
// ...
func getBitcoinData(url: String) {
Alamofire.request(url, method: .get)
.responseJSON { response in
if response.result.isSuccess {
print("Sucess! Got the bitcoin price data")
let responseJSON : JSON = JSON(response.result.value!)
self.updateBitcoinData(bitcoinJSON : responseJSON)
DispatchQueue.main.async {
NotificationCenter.default.post(name: Notification.Name.init("ReceivedBitcoinData"), object: nil)
}
}
else{
print("Error \(String(describing: response.result.error))")
}
}
}
// ...
}
在您的NetworkManager类中:
Notification.Name
您还可以为extension Notification.Name {
static let ReceivedBitcoinData = Notification.Name.init("ReceivedBitcoinData")
}
写一个扩展名,以避免由于输入错误而没有收到通知。
NotificationCenter.default.post(name: .ReceivedBitcoinData, object: nil)
扩展名用法示例:
update_board = ["#"," "," "," "," "," "," "," "," "," "]
def player_turn():
# Take in player's input so it can be added to the display board.
user_input = input('Choose your position: ')
if update_board[int(user_input)] == " ":
valid_input = True
else:
valid_input = False
while not valid_input:
user_input = input("That is not an option, please try again.\n> ")
if update_board[int(user_input)] == " ":
valid_input = True
else:
valid_input = False
return int(user_input)
player1 = "X"
update_board[(player_turn())] = player1