Некоторая общая перспектива картины, чтобы добавить к другим полезным, но более детальным ответам:
В Swift восклицательный знак появляется в нескольких контекстах:
- Принудительная распаковка:
let name = nameLabel!.text
- Неявно развернутые опции:
var logo: UIImageView!
- Принудительное литье:
logo.image = thing as! UIImage
- Необработанные исключения:
try! NSJSONSerialization.JSONObjectWithData(data, [])
Каждый из них представляет собой отдельную языковую конструкцию с различным значением, но у всех них есть три общие общие черты:
1. Восклицательные знаки обходят проверки безопасности Swift во время компиляции.
Когда вы используете !
Swift, вы, по сути, говорите: «Эй, компилятор, я знаю, что вы думаете, что здесь может произойти ошибка , но я знаю с полной уверенностью, что она никогда не будет».
Не весь действительный код вписывается в коробку системы типов во время компиляции Swift - или статическую проверку типов любого языка, в этом отношении. Существуют ситуации, когда вы можете логически доказать, что ошибка никогда не произойдет, но вы не можете доказать это компилятору . Вот почему дизайнеры Swift добавили эти функции в первую очередь.
Однако всякий раз, когда вы используете !
, вы исключаете наличие пути восстановления для ошибки, что означает, что ...
2. Восклицательные знаки - потенциальные сбои.
Восклицательный знак также гласит: «Эй, Свифт, я настолько уверен, что эта ошибка никогда не произойдет, что для тебя лучше вывести из строя все мое приложение, чем для меня написать код для его восстановления».
Это опасное утверждение. Это может быть правильным: в критически важном коде, где вы тщательно продумали инварианты своего кода, может оказаться, что фиктивный вывод хуже, чем сбой.
Тем не менее, когда я вижу !
в дикой природе, он редко используется так осознанно. Вместо этого это слишком часто означает: «это значение было необязательным, и я не особо задумывался о том, почему оно может быть нулевым или как правильно справиться с этой ситуацией, но добавляя!
делало его компилируемым… так что мой код верен, верно?»
Остерегайтесь высокомерия восклицательного знака. Вместо…
3. Восклицательные знаки лучше всего использовать экономно.
Каждая из этих !
конструкций имеет ?
аналог, который заставляет вас иметь дело с ошибкой / нулем:
- Условное развертывание:
if let name = nameLabel?.text { ... }
- Optionals:
var logo: UIImageView?
- Условные приведения:
logo.image = thing as? UIImage
- Исключения без ошибок:
try? NSJSONSerialization.JSONObjectWithData(data, [])
Если у вас есть соблазн использовать !
, всегда полезно тщательно обдумать, почему вы его не используете ?
. Действительно ли сбой вашей программы - лучший вариант, если !
операция не удалась? Почему это значение является необязательным / ошибочным?
Есть ли разумный путь восстановления, который ваш код мог бы использовать в случае nil / error? Если так, закодируйте это.
Если это не может быть ноль, если ошибка не может произойти, то есть ли разумный способ переработать вашу логику, чтобы компилятор знал это? Если так, сделайте это; Ваш код будет менее подвержен ошибкам.
Есть моменты, когда нет разумного способа обработки ошибки, и простое игнорирование ошибки - и, следовательно, обработка неверных данных - будет хуже, чем сбой. Это то время, чтобы использовать распаковку силой.
Я периодически ищу всю свою кодовую базу !
и проверяю каждое ее использование. Очень немногие обычаи выдерживают проверку. (На момент написания этой статьи вся структура Siesta имела ровно два экземпляра .)
Это не значит, что вы никогда не должны использовать !
в своем коде - просто вы должны использовать его осознанно и никогда не делать его опцией по умолчанию.