【问题标题】:cannot use optional chaining on non-optional value of type 'Any' SWIFT不能对“任何”SWIFT 类型的非可选值使用可选链接
【发布时间】:2023-04-02 16:40:01
【问题描述】:

我对 Swift 非常陌生,并且在构建一个使用名为 openweathermap.org 的网站的 API 的天气应用程序时遇到了麻烦。当用户输入一个城市并单击“提交”时,他们应该能够看到一个显示天气描述的标签。

JSON 中的结果是:

(
        {
        description = haze;
        icon = 50d;
        id = 721;
        main = Haze;
    },
        {
        description = mist;
        icon = 50d;
        id = 701;
        main = Mist;
    }
)

在尝试调试时,我使用了代码:print(jsonResult["weather"]!),这让我可以看到上面的 JSON 详细信息。但是,当我尝试获取天气描述时,我似乎无法让它工作。

我的目标:我试图让天气描述显示在我的应用程序上。我目前收到错误消息:不能对“任何”类型的非可选值使用可选链接。您的帮助将不胜感激!

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var cityTextField: UITextField!

    @IBOutlet weak var resultLabel: UILabel!


    @IBAction func submit(_ sender: AnyObject) {
        // getting a url
        if let url = URL(string: "http://api.openweathermap.org/data/2.5/weather?q=" + (cityTextField.text?.replacingOccurrences(of: " ", with: "%20"))! + ",uk&appid=08b5523cb95dde0e2f68845a635f14db") {

        // creating a task from the url to get the content of that url
        let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
            if error != nil {
                print("error")
            } else {
                print("no error")
                if let urlContent = data {
                    do {
                        let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String:Any]
                        //print(jsonResult["weather"]!)
                        if let description = jsonResult["weather"]??[0]["description"] as? String {
                            DispatchQueue.main.sync(execute:{
                                self.resultLabel.text = description
                            })
                        }
                    } catch {
                        print("JSON processing failed")
                    }
                }
            }
        }
        task.resume()
        } else {
            resultLabel.text = "Couldn't find weather for that city. Please try a different city."
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    }

【问题讨论】:

  • 这里有两个问号(在天气之后):jsonResult["weather"]??[0]["description"] 尝试删除其中一个,看看是否能让你更进一步
  • 这篇文章值得一读:developer.apple.com/swift/blog/?id=37(我知道你可能已经阅读了足够多的书,但是这篇文章给出了 - 我认为 - 一个很好的介绍,介绍了在 Swift 中使用可选的初始化程序解析 JSON例如)
  • @pbodsk 感谢您的提示!
  • @pbodsk 我一定会阅读那篇文章。谢谢! :-)

标签: ios json swift


【解决方案1】:

试试这个

let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String:Any]


    let weather = jsonResult["weather"] as! [[String : Any]]
    if let description = weather[0]["description"] as? String {

        print(description)
    }

【讨论】:

  • 你的答案中的 myjson 变量是什么?
  • hoops.. 抱歉,这是 jsonResult
  • @Rob 非常感谢!!!这就像一个魅力。我非常感谢您的有用回答……这让我很开心。 :-D
  • @AdrianaGiancarlaPope 欢迎 ;)
【解决方案2】:

您在这里使用“??”混淆了编译器

if let description = jsonResult["weather"]??[0]

正确的语法是使用一个“?”

if let description = jsonResult["weather"]?[0]

但是你会得到另一个错误,因为在该行中:

let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String:Any]  

你说jsonResult["weather" 会给你输入Any。不输入数组。

所以你需要像这样的数组解包:

if let descriptions = jsonResult["weather"] as? [[String : Any]], let description = descriptions[0]

等等。

【讨论】:

  • 感谢您的帮助! :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-03
  • 1970-01-01
  • 1970-01-01
  • 2014-08-04
  • 1970-01-01
  • 2017-03-29
  • 2023-03-24
相关资源
最近更新 更多