2016-08-11 85 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()相比,只需強制展開可選,以至少可以提供錯誤消息。