Site icon AppTractor

Безопасное программирование в Swift

Представьте себе такой сценарий. Вы только что обновили свое приложение и вышли, чтобы выпустить пар. Пока вы расслабляетесь, ваш телефон начинает звонить снова и снова. Ваша последняя сборка дает сбои чаще, чем 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()
}

Суть истории

Что вы должны вынести из этой статьи — вы никогда, НИКОГДА не должны оставлять необязательные значения не проверенными.

Краткий обзор того, когда каждый управляющий оператор более полезен:

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

Источник

Exit mobile version