Не использовать разворачивание в операторах защиты

Я понимаю использование необязательных параметров достаточно, чтобы знать, когда необходимо развернуть необязательный элемент с помощью восклицательного знака. Почему восклицательный знак не нужен в операторе защиты?

Этот код работает и компилируется, но не использует восклицательные знаки:

struct Blog{

  var author:String?
  var name: String?

}

func blogInfo2(blog:Blog?){
  guard let blog = blog else {
    print("Blog is nil")
    return
  }
  guard let author = blog.author, name = blog.name else {
    print("Author or name is nil")
    return
  }
  print("BLOG:")
  print(" Author: \(author)")
  print(" name: \(name)")
}

Этот код также работает, если вы ставите восклицательные знаки:

struct Blog{

  var author:String?
  var name: String?

}

func blogInfo2(blog:Blog?){
  guard let blog = blog! else {
    print("Blog is nil")
    return
  }
  guard let author = blog.author!, name = blog.name! else {
    print("Author or name is nil")
    return
  }
  print("BLOG:")
  print(" Author: \(author)")
  print(" name: \(name)")
}

Разве это не немного противоречиво или кто-то может четко объяснить, почему восклицательный знак не нужен?


person Laurence Wingo    schedule 15.07.2016    source источник
comment
Я удивлен, что у вас работает версия guard let blog = blog!. Какую версию Swift вы используете?   -  person Phillip Mills    schedule 15.07.2016
comment
@PhillipMills да, теперь я понимаю, попробовав это в быстром онлайн-компиляторе, потому что я использую бета-версию Xcode 8.   -  person Laurence Wingo    schedule 15.07.2016


Ответы (3)


guard let unwrapped = optional — это Необязательная привязка (к сожалению, нет прямой ссылки на нужный раздел книги). Он безопасно пытается развернуть значение в необязательном параметре. Если есть значение, развертывание завершается успешно, и значение присваивается заданному имени.

Вы должны сильно отдавать предпочтение использованию необязательных привязок с guard или if (разница заключается в области действия «развернутого» имени) по сравнению с использованием принудительной развертки с !. Неудачная принудительная развертка является фатальной ошибкой; ваша программа просто рухнет.

person jscs    schedule 15.07.2016

Я понимаю использование необязательных параметров достаточно, чтобы знать, когда необходимо развернуть необязательный элемент с помощью восклицательного знака.

У меня такое чувство, что вы недостаточно понимаете опции Swift, если делаете такое утверждение.

Контракт, стоящий за опционом, заключается в том, что он может быть нулевым, а может и не быть; вы этого не знаете, и поэтому вам нужно развернуть это (например, открыть коробку и посмотреть, что внутри), прежде чем вы сможете сказать.

Поле может быть пустым (ноль необязательно) или может содержать значение.

Существует очень мало причин для использования принудительной развертки (!). Очень мало, и обычно это считается плохой практикой в ​​большинстве (но не во всех) случаях.

Продолжая аналогию, принудительно разворачивая вещи, вы говорите в этом ящике что-то есть, и я хочу, чтобы вы мне доверяли и не проверяли.

Зная, что пустое поле приведет к сбою вашего приложения, это очень опасно, учитывая, что в Swift были введены дополнительные параметры, чтобы защитить вас от таких сбоев с самого начала. .

Операторы if let/guard let в основном заглядывают внутрь коробки, и если там что-то есть, они дают это вам, но они также дают вам возможность сделать что-то еще, если коробка пуста.

Xcode принудительно разворачивает при использовании IBOutlets, потому что по дизайну контракт заключается в том, что эти объекты будут доступны к тому времени, когда вы сможете использовать их в своем представлении. контроллер, но если вы не уверены на 100%, что значение не будет nil, то почти всегда лучше (и на будущее) использовать оператор guard (или if).

По моему опыту, даже если вы знаете наверняка, все же безопаснее выбросить guard и забыть о будущих проблемах, которые могут возникнуть.

person Martin Marconcini    schedule 15.07.2016
comment
Я бы сказал, что использование ! ограничено двумя случаями. a/ когда вы не можете исправить эту ошибку (например, nil возвращается из-за неудачного выделения памяти) b/ когда nil следует рассматривать как ошибку программирования. Например, при создании URL из строки литерал. В этом случае ! работает как утверждение. - person Sulthan; 15.07.2016
comment
@Sulthan Согласитесь, что в очень немногих случаях ! в порядке, обычно это зависит от проекта, но обычно предпочтительнее изящно обрабатывать ошибку (сбой выделения памяти) и предлагать альтернативу или информировать пользователя о том, что произошло, чем простая авария; авария — худший из возможных исходов, избегайте ее любой ценой. Язык/фреймворк дает вам инструменты для этого. - person Martin Marconcini; 16.07.2016

Восклицательный знак «force» разворачивает необязательный элемент. guard let или if let разворачивает его, ничего не форсируя, поэтому восклицательный знак не используется.

person Aaron Brager    schedule 15.07.2016