学习Swift,创建对象时未解包的可选类型的值

时间:2016-01-09 17:45:38

标签: swift

我现在正在学习Swift,在课程中我们有一个教训来制作一个简单的应用程序。现在我遇到了一些文本字段编程问题但是它无法正常工作。

这是我的代码:

class ViewController: UIViewController {

    @IBOutlet weak var refeicaoField: UITextField?
    @IBOutlet weak var felicidadeField: UITextField?


    @IBAction func addRefeicao(sender: UIButton) {

        if refeicaoField == nil || felicidadeField == nil {
            return
        }

        let nomeRefeicao = refeicaoField!.text
        let valorFelicidade = felicidadeField!.text
        let valorFelicidadeInt = Int(valorFelicidade!)

        let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt)
    }


}

问题从这里开始:

    let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt)

它所说的:可选的' Int?'没有打开;你的意思是使用'!'或'?'以及可选'字符串的价值?'没有打开;你的意思是使用'!'或者'?'

我有点困惑,因为在课程示例中他们这样做了:

    let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt!)

并且工作,但对我来说没有。如果我试着把'!'在这两个变量中,我有一个感叹号警告,提示不要使用novaRefeicao。

出了什么问题?

修改

使用此处的所有提示完成一些更改,现在我的代码就像:

class ViewController: UIViewController {

    @IBOutlet weak var refeicaoField: UITextField!
    @IBOutlet weak var felicidadeField: UITextField!


    @IBAction func addRefeicao(sender: UIButton) {

        if refeicaoField == nil || felicidadeField == nil {
            return
        }

        let nomeRefeicao = refeicaoField!.text
        let valorFelicidade = felicidadeField!.text

        if nomeRefeicao == nil {
            return
        }

        if let valorFelicidadeInt = Int(valorFelicidade!) {
            let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt)
        } else {
            return
        }
    }


}

现在我再次收到了解包的错误,但现在使用" nomeRefeicao"代替。试图把''!'在其中,但它表明让novaRefeicao是不可变的值。

3 个答案:

答案 0 :(得分:3)

你应该明白,Swift语言在过去的一年中已经改变了 lot ,并且随着时间的推移感叹号已经发生了很大的变化。如果你的例子来自2015年中期,你就会看到过时的语法。

值为?表示此项可能包含值...或者可能不包含值。

具有!的值意味着您强行打开一个相当危险的对象,谨慎使用它,并且只有当您确定它不会导致崩溃时才会使用它。

如果你有一个可选值,你可以安全地打开它:

guard let unwrapped = wrapped else {
    return
}

if let unwrapped = wrapped {
    print(unwrapped)
}

更多信息,如果你有一个初始化的可选值,你真正得到的是:

enum Optional<A> {
    case None
    case Some(A)
}

这就是为什么你不能在没有展开它的情况下使用你的价值...它被“包裹”在可选枚举中,它具有值或不具有值。

添加了一点保护措施的代码:

class ViewController: UIViewController {

    @IBOutlet weak var refeicaoField: UITextField?
    @IBOutlet weak var felicidadeField: UITextField?


    @IBAction func addRefeicao(sender: UIButton) {

        guard let refeicaoField = refeicaoField!.text else {
            return
        }

        guard let felicidadeField = felicidadeField!.text else {
            return
        }

        let nomeRefeicao = refeicaoField ?? "error" // added protection
        let valorFelicidade = felicidadeField ?? "error"  // added protection
        let valorFelicidadeInt = Int(valorFelicidade) ?? 0 // defaults to '0' in case of issue
    }
}

答案 1 :(得分:2)

text的{​​{1}}属性和UITextField初始化程序的结果都返回一个可选值。

因此,如果方法需要非可选参数,则必须打开两者

Int(string:String)

最紧凑的语法是

let novaRefeicao = Meal(nomeAlimento: nomeRefeicao!, alegriaEmComer: valorFelicidadeInt!)

class ViewController: UIViewController { @IBOutlet weak var refeicaoField: UITextField! @IBOutlet weak var felicidadeField: UITextField! @IBAction func addRefeicao(sender: UIButton) { if let nomeRefeicao = refeicaoField.text, valorFelicidade = felicidadeField.text, valorFelicidadeInt = Int(valorFelicidade) { let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt) // do something with novaRefeicao } } } 初始化程序仅在

时调用
  • Meal不是refeicaoField.text
  • nil不是felicidadeField.text,可以转换为nil

无需检查Int的{​​{1}}个实例 如果出现运行时错误,则其中一个字段未在IB中连接。

消息UITextField是一个警告,因为从未使用分配给nil的已创建Initialization of immutable value ...实例。这就是为什么我添加评论行做某事......

答案 2 :(得分:1)

该行:

any?

let valorFelicidadeInt = Int(valorFelicidade!) 值转换为String。如果字符串无法转换为整数,您的代码应该怎么做?你需要明确解决这个问题。

在Swift中,转换的类型为Int - 转换有效或无效。因此,您有两个案例要涵盖。以下是一种可能的方法:

Optional

如果if let valorFelicidadeInt = Int(valorFelicidade!) { let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt) // continue using `Meal` } else { // User error; text not an int } 返回非零可选项,if let将成功;然后,您将构建Int(...)

通过处理这两个选项进行解包的方法同样适用于代码的其他部分。