2016-08-11 81 views
2

我是swift的新手,我不太了解如何正确使用可选值。关于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. 给像属性的默认值:unwarp前值var name = ""
  2. 测试它想:

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

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

  1. 我认为在标签上显示的默认字符串比崩溃更可接受,因为未能取消任意值。
  2. 当我有更多的使用价值时,代码将非常漫长,难以阅读。

我选择了合适的吗?或者他们都不了解可选值的用法,有更好的方法吗?有人可以帮助我吗?

+0

我可以马上想到的一件事就是你将内存分配给可能以零值结束的变量。因此,你正在分配比你需要的更多的内存。 (这个分配可能是不重要的,但是需要考虑的事实) – Harsh

+2

你不想做默认值方法('var name =“”')。可选的绑定('如果let name = user.name {nameLabel.text = name}')_unwrap_可选肯定是要走的路。或者使用'nil' colaescing操作符''',就像pbrush25给你看的那样。但是“没有名字时应该显示什么”问题是用户界面问题(在设置标签的“文本”时完成),而不是您通常希望构建到模型中的内容。在没有数据的情况下,在模型中使用'nil'是正确的方法。 – Rob

回答

3

您可以放心地解开可选或给它一个默认值不宣而像这样一个新的变量:

nameLabel.text = user.name ?? "" 

这就是所谓的零合并运算,并会尝试解开一个可选的,如果解包如果不成功,将会给它放置在操作符的rhs上的默认值。

3

你的直觉是正确的强制展开可选是不明智的。提供非零缺省值的做法也是正确的,因为它违背了可选的目的。

if let foo = user.name结合是这样做的合理途径,但如果你正在做的是分配一个值,你可以通过使用无合并运算饶了自己的大括号,如pbush25规定:

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

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

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

即使您希望在可选值为零的情况下发生崩溃,与assert或使用preconditionFailure()相比,只需强制展开可选,以至少可以提供错误消息。