解析json时使用未解析的标识符

时间:2018-02-22 18:39:54

标签: json swift parsing

let url = URL(string: "https://api.coindesk.com/v1/bpi/currentprice.json")
    let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
        if error != nil {
            print ("Error!")
        } else {
            if let content = data {
                do {
                    let myJson = try JSONSerialization.jsonObject(with: content) as! [String:Any]
                    if let rates = myJson["bpi"] as? [String:Any] {
                        if let currency = rates["USD"] as? [String:Any] {
                            if let btc = currency["rate"] as? String {
                                DispatchQueue.main.async{
                                    self.bitcoinlabel.text = "$" + btc

                                }
                            }
                        }
                    }
                }
                catch{
                    print(error)
                }
            }
        }
    }
    task.resume()

    let btcprice: Double = btc

问题出在最后一行(使用未解析的标识符'btc')。如何从数据中导出值,以便在代码块之外或其他函数中使用。

2 个答案:

答案 0 :(得分:0)

外部作用域中无法访问

btc。你应该只在定义它的范围内做任何你想做的事情。

像这样:

if let btc = currency["rate"] as? String {
    DispatchQueue.main.async{
        self.bitcoinlabel.text = "$" + btc
        let btcprice: Double = btc
        // Do Stuff here with btcprice
        // OR Call another func from here like someFunctionWhichUsesTheBtcprice()
        // OR Add CompletionHandler in the Method definition like : completion: @escaping (()->()) and pass the function you want to call after you get the response with the method and call that function here like: completion()
    }
}

另外,如果您将btcprice声明为var btcprice: Double?之类的类变量,则应仅在该块中指定self.btcprice = btc。但是,只有在API返回响应后才能使用它来做任何事情,否则btcprice将是nil

更新代码:

您可以使用以下内容:

func callAPI(completion: @escaping (Double) -> ()) {
    // Call Your API Here...
    let url = URL(string: "https://api.coindesk.com/v1/bpi/currentprice.json")
    let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
        if error != nil {
            print ("Error!")
        } else {
            if let content = data {
                do {
                    let myJson = try JSONSerialization.jsonObject(with: content) as! [String:Any]
                    if let rates = myJson["bpi"] as? [String:Any] {
                        if let currency = rates["USD"] as? [String:Any] {
                            if let btc = currency["rate"] as? String {
                                DispatchQueue.main.async{
                                    self.bitcoinlabel.text = "$" + btc
                                    if let btcDoubleValue = Double(btc) {
                                        // This will be called when we will get the response and btc value
                                        completion(btcDoubleValue)
                                    }
                                }
                            }
                        }
                    }
                }
                catch{
                    print(error)
                }
            }
        }
    }
    task.resume()
}

这样称呼:

self.callAPI() { (btcprice) in
   // Do your stuff here
}

答案 1 :(得分:0)

你可以将它声明为实例变量,但请记住,对API的调用是异步的,因此在响应返回之前它的值不会是真实的,在类范围中声明btc

 var btc: Double?

然后

                if let btc = currency["rate"] as? String {
                            DispatchQueue.main.async{
                                self.bitcoinlabel.text = "$" + btc
                                self.btc = btc 
                            }
                        }