2016-08-11 7 views
2

Я новичок в быстром, и я действительно не понимаю, как правильно использовать опциональное значение.Confused о необязательном значении в 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 для получения значений из сервера и обновления пользовательского интерфейса. Код:

class UserViewController: UIViewController { 

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

    override func viewDidLoad() { 
     super.viewDidLoad() 

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

} 

Я думаю, что это опасный способ справиться с этой работой, потому что нет ничего может гарантировать, что у меня есть определенное имя, когда я хочу поставить его на этикетке. Он работает очень хорошо в большинстве случаев, но может потерпеть крах, когда не получается получить правильное значение с сервера (например, для ключа «имя» нет значения).

У меня есть две идеи о вопросах выше:

  1. Дайте значение по умолчанию для свойства, как: var name = ""
  2. Теста значение до unwarp это нравится:

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

Я хочу выбрать первый путь, потому что:

  1. Я думаю, что показать строку по умолчанию на ярлыке гораздо более приемлемо, чем сбой, потому что не удалось опознать необязательное значение.
  2. Когда у меня есть намного больше значений для использования, код будет очень длинным и отличным для чтения.

Я выбрал правильный вариант? Или оба они не понимали использование необязательной ценности, и есть лучший способ? Кто-то может мне помочь?

+0

Одна вещь, которую я могу сразу придумать из коробки, заключается в том, что вы выделяете память переменным, которые могли бы иметь значения nil. Следовательно, вы выделяете больше памяти, чем вам когда-либо понадобится. (Это распределение может быть неинтересным, но факт должен быть рассмотрен) – Harsh

+2

Вы не хотите использовать подход по умолчанию ('var name =" "'). Необязательная привязка ('if 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"

Это означает «развернуть имя пользователя.имя, и если его значение не равно нулю, используйте его. В противном случае используйте следующее значение:« Вы можете даже связать их вместе, если, например, вы хотели использовать идентификатор пользователя в качестве резервной метки текст, но идентификатор также может отсутствовать:

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

Даже если вы хотите сбой в случае, если необязательное значение равно нулю, было бы лучше, чтобы assert или использовать preconditionFailure(), а не просто принудительно развернуть дополнительный, чтобы вы могли хотя бы предоставить сообщение об ошибке.