Представьте себе такой сценарий. Вы только что обновили свое приложение и вышли, чтобы выпустить пар. Пока вы расслабляетесь, ваш телефон начинает звонить снова и снова. Ваша последняя сборка дает сбои чаще, чем Windows Vista!
По моему опыту, в 9 из 10 случаев неожиданные сбои происходят из-за того, что переменная, которая предположительно всегда должна имеет значение… не имеет его. Чтобы не получать легкий сердечный приступ каждый раз, когда вы выходите из дома и звонит телефон, давайте рассмотрим некоторые принципы, которым вы можете следовать в программировании, чтобы свести к минимуму такие сбои.
Всегда указывайте значение по умолчанию
Swift предлагает разработчикам очень удобный способ указать значение при использовании переменной, если оно равно nil. Давайте посмотрим на пример ниже:
Server.request("getNumberOfLikes") { (response, error) in self.numberOfLikes = response as! Int self.updateUI() }
Вы заметили проблему? Хотя это считается ошибкой новичка, это может случиться и с более опытными разработчиками. Если вы не заметили, то вот куда нужно смотреть:
response as! Int
Независимо от того, насколько вы уверены, что response всегда будет там, наступит момент, когда что-то пойдет не так, и ваше приложение обязательно упадет.
Скорее всего, это может произойти из-за изменений, которое вы или кто-то другой внесете в будущем. Параметр или возвращаемое значение сейчас могут быть обязательными, но в будущем ваша бизнес-логика может измениться и они превратятся в необязательные. Поэтому, когда эти изменения вступят в силу, высока вероятность того, что ваше приложение будет массово аварийно завершать работу.
Вот что вы всегда должны делать, чтобы избежать такой катастрофы:
Server.request("getNumberOfLikes") { (response, error) in self.numberOfLikes = response as? Int ?? 0 self.updateUI() }
Давайте быстро посмотрим, что изменилось.
Эти ?? называются оператором нулевого слияния (оператор объединения по nil, nil coalescing operator) и он идет рука об руку с optional значениями. Вместо того, чтобы проверять, является ли переменная nil, и если да, присваивать ей значение, оператор нулевого слияния может сделать это по умолчанию. На самом деле он проверяет, дает ли выражение слева nil, и если да, то присваивает переменной значение, которое вы указали справа. В противном случае он безопасно разворачивает переменную.
if-let выражение
Хотя оператор объединения может быть полезен, бывают случаи, когда вам нужно добавить немного больше логики в свой код. Например, в тех случаях, когда вы знаете, что значение иногда может быть нулевым, а иногда нет, вы должны использовать оператор if-let.
Например:
Server.request("getNumberOfLikes") { (response, error) in if response != nil { self.numberOfLikes = response as! Int } self.updateUI() }
Хотя приведенный выше случай кажется более безопасным, чем принудительное развертывание переменной, он все равно может привести к сбою. Что произойдет, если ответ действительно не нулевой, но по какой-то причине это больше не Int?
Вместо этого воспользуемся оператором if-let и посмотрим, что произойдет:
Server.request("getNumberOfLikes") { (response, error) in if let numberOfLikes = response as? Int { self.numberOfLikes = numberOfLikes } self.updateUI() }
Выглядит намного лучше сейчас, да? Таким образом, вы можете точно проверить, что вы ожидаете получить, самым безопасным способом! Конечно, вы всегда можете добавить дополнительные проверки в том же операторе if-let, например:
Server.request("getNumberOfLikes") { (response, error) in if let numberOfLikes = response as? Int, let variable2 = something as? Type, let variable3 = somethingElse as? Type { ... } self.updateUI() }
Оператор if-let будет считаться действительным только в том случае, если все подоператоры не равны нулю. Очевидно, что при необходимости вы можете добавить операторы else-if-let и else.
guard-let выражение
Оператору guard-let не нужно объявлять переменную для использования, но это плюс. Вы найдете его более полезным в случаях, когда вы хотите полностью остановить поток кода.
Server.request("getNumberOfLikes") { (response, error) in guard let numberOfLikes = response as? Int else { return } self.updateUI() }
В этом примере функция updateUI будет вызываться только в том случае, если оператор guard-let не возвращает значение. Если вы просто хотите проверить, содержит ли переменная значение, не сохраняя ее где-то, а если нет, вернуться, то вы можете сделать это:
Server.request("getNumberOfLikes") { (response, error) in guard response as? Int else { return } self.updateUI() }
Суть истории
Что вы должны вынести из этой статьи — вы никогда, НИКОГДА не должны оставлять необязательные значения не проверенными.
Краткий обзор того, когда каждый управляющий оператор более полезен:
- ?? — оператор нулевого слияния позволяет указать значение по умолчанию для переменной в случае, если оно равно нулю. Вы должны использовать его в случаях, когда вы всегда ожидаете значение.
- if-let — оператор помогает безопасно развернуть необязательные параметры, которые могут иметь или не иметь значения.
- guard-let — оператор лучше всего подходит для случаев, когда вам нужно экранировать блок кода, когда переменная или набор переменных равны нулю или не соответствуют предоставленным вами проверкам.
Я надеюсь, что после того, как вы прочитали мой, без сомнения, идеальный туторил, вы получили представление о том, как сделать ваши приложения менее подверженными сбоям и ошибкам.