2

我是 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”没有值)。

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

  1. 为属性提供默认值,例如:var name = ""
  2. 在 unwarp 之前测试该值,如下所示:

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

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

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

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

4

2 回答 2

3

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

nameLabel.text = user.name ?? ""

这称为 nil 合并运算符,它将尝试解包一个可选项,如果解包不成功,将给它您放置在运算符 rhs 上的默认值。

于 2016-08-11T19:00:21.490 回答
3

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

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还是使用 apreconditionFailure()而不是简单地强制解开可选值,以便您至少可以提供错误消息。

于 2016-08-11T19:18:26.797 回答