Деякі перспективи великої картини, які можна додати до інших корисних, але більш деталізованих відповідей:
У Swift знак оклику з’являється у кількох контекстах:
- Примусове розгортання:
let name = nameLabel!.text
- Неявно розгорнуті опції:
var logo: UIImageView!
- Примусове лиття:
logo.image = thing as! UIImage
- Неопрацьовані винятки:
try! NSJSONSerialization.JSONObjectWithData(data, [])
Кожен з них - це інша мовна конструкція з різним значенням, але всі вони мають три важливі речі:
1. Знак оклику оминає перевірки безпеки Свіфта за час збирання.
Коли ви користуєтесь !
Swift, ви по суті говорите: "Ей, компілятор, я знаю, ти думаєш, що тут може статися помилка , але я знаю з цілковитою впевненістю, що цього ніколи не буде".
Не весь дійсний код вписується у вікно системи типу компіляції Swift - або статична перевірка будь-якої мови для цього питання. Є ситуації, коли можна логічно довести, що помилка ніколи не трапиться, але ви не можете довести її компілятору . Ось чому дизайнери Swift додали ці особливості в першу чергу.
Однак щоразу, коли ви використовуєте !
, ви виключаєте наявність помилки на відновлення, що означає, що ...
2. Знак оклику - це потенційні аварії.
Знак оклику також говорить: "Ей, Свіфт, я настільки впевнена, що ця помилка ніколи не може трапитися, що вам краще зірвати всю програму, ніж мені, щоб кодувати шлях відновлення для неї".
Це небезпечне твердження. Це може бути правильним: у критичному для місії коді, де ви багато задумалися над інваріантами вашого коду, можливо, помилковий вихід є гіршим, ніж збій.
Однак, коли я бачу !
в дикій природі, його рідко використовують так розумно. Натомість це занадто часто означає: "це значення було необов’язковим, і я насправді не надто важко думав, чому він може бути нульовим або як правильно впоратися з цією ситуацією, але додавання !
змусило його скласти ... так що мій код правильний, правда?"
Остерігайтеся зарозумілості оклику. Натомість…
3. Знак оклику найкраще використовувати вкрай сумно.
Кожна з цих !
конструкцій має ?
аналог, який змушує вас мати справу з випадком помилки / нуля:
- Умовне розгортання:
if let name = nameLabel?.text { ... }
- Необов’язково:
var logo: UIImageView?
- Умовні ролі:
logo.image = thing as? UIImage
- Винятки з відмовою від відмови:
try? NSJSONSerialization.JSONObjectWithData(data, [])
Якщо ви спокушаєтесь користуватися !
, завжди добре продумати, чому ви не використовуєте ?
натомість. Чи є збій вашої програми справді найкращим варіантом, якщо !
операція не працює? Чому це значення необов’язкове / недоступне?
Чи є розумний шлях відновлення, який ваш код може пройти у випадку нуля / помилки? Якщо так, кодуйте це.
Якщо вона не може бути нульовою, якщо помилка ніколи не може статися, то чи є розумний спосіб переробити свою логіку, щоб компілятор це знав? Якщо так, зробіть це; ваш код буде менш схильний до помилок.
Бувають випадки, коли немає розумного способу вирішити помилку, а просто ігнорувати помилку - і, таким чином, діяти з помилковими даними - було б гірше, ніж збій. Це часи використання сили розкручування.
Я періодично шукаю всю свою кодову базу !
та перевіряю кожне її використання. Дуже мало звичаїв стоять на огляд. (Станом на це написання, у всій системі Siesta є рівно два екземпляри .)
Це не означає, що ви ніколи не повинні використовувати !
у своєму коді - просто, щоб ви користувалися ним усвідомлено , і ніколи не робили його параметром за замовчуванням.