对 swift 中的可选值感到困惑

Posted

技术标签:

【中文标题】对 swift 中的可选值感到困惑【英文标题】:Confused about optional value in swift 【发布时间】:2016-08-11 18:54:55 【问题描述】:

我是 swift 新手,不太了解如何正确使用可选值。

情况是:首先,我有一个模型类来存储其属性的一些值,并将请求发送到服务器以获取值。代码:

import Foundation

class User: NSObject 

    var name: String?

    func getInfo(updateUI: () -> ()) 
        let manager = AFHTTPSessionManager()
        manager.POST(URLString, parameters: nil, success:  (task: NSURLSessionDataTask, responseObject: AnyObject?) in

            let dic = responseObject as? NSDictionary
            self.name = dic?.objectForKey("name")
            updateUI()

        , failure:  (task: NSURLSessionDataTask?, error: NSError) in
            log.obj(error)
    )


其次,我想在 ViewController 中使用此模型从服务器获取值并更新 UI。代码:

class UserViewController: UIViewController 

    @IBOutlet var nameLabel: UILabel!
    var user = User()

    override func viewDidLoad() 
        super.viewDidLoad()

        user.getInfo(
            nameLabel.text = user.name!
        )
    


我认为处理这项工作是一种危险的方式,因为当我想把它放在标签上时,没有任何东西可以确保我有一个特定的名字。它在大多数情况下工作得很好,但是当无法从服务器获取正确的值时它可能会崩溃(例如,键“name”没有值)。

关于上述问题,我有两个想法:

    为以下属性提供默认值:var name = ""

    在解开它之前测试该值:

    if let foo = user.name 
        nameLabel.text = foo
    
    

我想选择第一种方式,因为:

    我认为在标签上显示默认字符串比崩溃更容易接受,因为无法解开可选值。 当我要使用更多值时,代码会很长且难以阅读。

我选对了吗?或者他们俩都不了解可选值的用法并且有更好的方法?有人可以帮助我吗?

【问题讨论】:

我可以立即想到的一件事是,您正在将内存分配给可能以 nil 值结束的变量。因此,您分配的内存比以往任何时候都多。 (这种分配可能微不足道,但需要考虑的事实) 您不想使用默认值方法 (var name = "")。可选绑定 (if let name = user.name nameLabel.text = name ) 到 unwrap 可选绝对是要走的路。或者使用nil colaescing 运算符??,就像pbrush25 向您展示的那样。但是“没有名称时我应该显示什么”问题是一个用户界面问题(在设置标签的 text 时完成),而不是您通常想要构建到模型中的问题。当没有数据时,在模型中添加nil 是正确的方法。 【参考方案1】:

您可以安全地打开一个可选的包装或给它一个默认值,而无需像这样声明一个新变量:

nameLabel.text = user.name ?? ""

这被称为 nil 合并操作符,它会尝试解开一个可选项,如果解开不成功,将给它一个默认值,你已经放在操作符的 rhs 上。

【讨论】:

【参考方案2】:

您的直觉是正确的,强制展开可选选项是不明智的。您也正确的是,提供非零默认值会破坏可选项的目的。

if let foo = user.name 绑定是一种不错的方法,但如果您所做的只是分配一个值,您可以使用 nil 合并运算符来避免花括号,如 pbush25 所述:

nameLabel.text = user.name ?? "Default Label Text"

这意味着“解开 user.name,如果它的值不是 nil,则使用它。否则,使用以下值:”你甚至可以将它们链接在一起,例如,如果你想使用用户的 ID 作为后备标签文本,但 ID 也可能不存在:

nameLabel.text = user.name ?? user.id ?? "No name or ID".

即使您想在可选值为 nil 的情况下崩溃,也最好使用assert 或使用preconditionFailure(),而不是简单地强制解开可选值,以便您至少可以提供错误消息.

【讨论】:

以上是关于对 swift 中的可选值感到困惑的主要内容,如果未能解决你的问题,请参考以下文章

Swift 中的可选类型错误:致命错误:在展开可选值时意外发现 nil

swift 通过枚举匹配的可选值(模式)

可选类中的可选属性 VS 可选字典中的可选值

Swift - 将 nil 核心数据字符串转换为可选值

Swift函数式编程四(可选值)

Swift函数式编程四(可选值)