如何使用函数中的JSON数据更新Swift 3中的标签?

如何使用函数中的JSON数据更新Swift 3中的标签?,swift,xcode,Swift,Xcode,出于某种原因,每当我试图使用DispatchQueuecode块内部的self.infoLabel.text=String(temp!)用当前温度更新标签时,我会收到以下致命错误消息: unexpectedly found nil while unwrapping an Optional value. 如果有人能帮我找出下面的代码不起作用的原因,我将不胜感激。谢谢 func getCurrentTemp(city: String){ let weatherRequestURL = U

出于某种原因,每当我试图使用
DispatchQueue
code块内部的
self.infoLabel.text=String(temp!)
用当前温度更新标签时,我会收到以下致命错误消息:

unexpectedly found nil while unwrapping an Optional value.
如果有人能帮我找出下面的代码不起作用的原因,我将不胜感激。谢谢

func getCurrentTemp(city: String){

    let weatherRequestURL = URL(string: "\(openWeatherMapBaseURL)?APPID=\(openWeatherMapAPIKey)&q=\(city)")!

    // The data task retrieves the data.


    URLSession.shared.dataTask(with: weatherRequestURL) { (data, response, error) in

        if let error = error {
            // Case 1: Error

            print("Error:\n\(error)")
        }
        else {

            //print("Raw data:\n\(data!)\n")
            //let dataString = String(data: data!, encoding: String.Encoding.utf8)
            //print("Human-readable data:\n\(dataString!)")

            do {
                // Try to convert that data into a Swift dictionary
                let weather = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String:AnyObject]

                if let main = weather["main"] as? [String: Any] {

                    let temp = main["temp"] as? Double
                    print("temp\(temp!)")

                    DispatchQueue.main.sync(execute: {




                        self.infoLabel.text = String(temp!)

                    })
                    //return temp as? String

                    //let temp_max = main["temp_max"] as? Double
                    //print("temp\(temp_max!)")

                    //let temp_min = main["temp_min"] as? Double
                    //print("temp\(temp_min!)")

                }
            }
            catch let jsonError as NSError {
                // An error occurred while trying to convert the data into a Swift dictionary.
                print("JSON error description: \(jsonError.description)")
            }

        }
    }

    .resume()


}

这里有两种可能性:1)temp为零(不应该是,因为您已经在上面的打印语句中强制将其展开)2)或infoLabel为零,如果您断开了插座连接,则会发生这种情况

它容易检查;在分配上方设置断点,并在调试控制台中键入:

po self.infoLabel
看看是不是零。为了更好地测量,您还需要检查温度


您还可以添加一个print语句来检查self.infoLabel或assert。

好的,所以我找到了解决这个问题的临时解决方案(见下文)。我没有将代码放在我创建的函数中,而是将其放在viewDidLoad()函数中。无论出于何种原因,
self.infoLabel?
在我创建的函数中的任何地方都是零

override func viewDidLoad() {

    super.viewDidLoad()

    // Do any additional setup after loading the view.

    print("Sucessful launched weather page.")


    let weatherRequestURL = URL(string: "\(openWeatherMapBaseURL)?APPID=\(openWeatherMapAPIKey)&q=\(city)")!

    // The data task retrieves the data.


    URLSession.shared.dataTask(with: weatherRequestURL) { (data, response, error) in

        if let error = error {
            // Case 1: Error

            print("Error:\n\(error)")

        }
        else {

            //print("Raw data:\n\(data!)\n")
            //let dataString = String(data: data!, encoding: String.Encoding.utf8)

            //print("Human-readable data:\n\(dataString!)")



            do {
                // Try to convert that data into a Swift dictionary
                let weather = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String:AnyObject]


                if let main = weather["main"] as? [String: Any] {

                    let temp = main["temp"] as? Double
                    print("temp\(temp!)")

                    var tempInFarenheit = ((9/5)*((temp!)-273) + 32).rounded()
                    DispatchQueue.main.sync(execute: {


                    self.infoLabel.text = "\(tempInFarenheit) + °"

                    })
                }

            }

            catch let jsonError as NSError {
                // An error occurred while trying to convert the data into a Swift dictionary.
                print("JSON error description: \(jsonError.description)")
            }

        }
        }

        .resume()


}

虽然这不是最有效的方法,但希望它能帮助其他有同样问题的人。如果我能找到一种更有效的方法,我一定会编辑这篇文章并将其包括在内。

非常感谢您抽出时间回复。我尝试了这个,并重拨了插座,它仍然给我相同的错误信息。我注意到,当上述函数中的任何地方(在原始代码中)不起作用时,当我尝试在viewDidLoad()中更改infoLabel的文本时,它成功地起作用。对于问题可能是什么,真的很困惑:-/调用是异步的。标签返回时是否存在?就这一点而言,自我存在吗?另外,要验证是否是标签导致了崩溃,请使用可选链接,而不是隐式展开:self.infoLabel?.text。您还可以打印出self以查看它是否有值。如果异步调用完成时调用的视图控制器不再存在,您可能需要对self进行弱引用或无主引用并退出。只需测试它,在函数内部,使用
print(self.InfoLabel?.text)
将打印nil,而在viewDidLoad()中使用
print(self.InfoLabel?.text)
,返回它的正确值。函数self的内部也有它的期望值。