Niektóre duże perspektywy do dodania do innych przydatnych, ale bardziej szczegółowych odpowiedzi:
W Swift wykrzyknik pojawia się w kilku kontekstach:
- Wymuszone rozpakowywanie:
let name = nameLabel!.text
- Niejawnie nieopakowane opcje:
var logo: UIImageView!
- Wymuszone odlewanie:
logo.image = thing as! UIImage
- Nieobsługiwane wyjątki:
try! NSJSONSerialization.JSONObjectWithData(data, [])
Każda z nich jest inną konstrukcją językową o innym znaczeniu, ale wszystkie one mają trzy ważne cechy wspólne:
1. Wykrzykniki omijają kontrole bezpieczeństwa Swift w czasie kompilacji.
Kiedy używasz !
w Swift, zasadniczo mówisz: „Hej, kompilatorze, wiem, że myślisz, że tutaj może się zdarzyć błąd , ale wiem z całkowitą pewnością, że nigdy nie nastąpi”.
Nie wszystkie poprawne kody mieszczą się w polu systemu typu czas kompilacji Swift - czy w tym przypadku statycznym sprawdzaniu typu w dowolnym języku. Są sytuacje, w których można logicznie udowodnić, że błąd nigdy nie wystąpi, ale nie można tego udowodnić kompilatorowi . Właśnie dlatego projektanci Swift dodali te funkcje w pierwszej kolejności.
Jednak za każdym razem, gdy używasz !
, wykluczasz ścieżkę odzyskiwania dla błędu, co oznacza, że…
2. Wykrzykniki to potencjalne awarie.
Wykrzyknik mówi również: „Hej, Swift, jestem tak pewien, że ten błąd nigdy nie może się zdarzyć, że lepiej jest, abyś zawiesił całą moją aplikację niż dla mnie kodowanie ścieżki odzyskiwania”.
To niebezpieczne twierdzenie. To może być prawidłowa: w krytycznych kodu, w którym można było pomyśleć o ciężko niezmienników kodzie jest, być może, że wyjście podrobiony jest gorsza niż w wypadku.
Jednak gdy widzę !
na wolności, rzadko używa się go tak uważnie. Zamiast tego zbyt często oznacza: „ta wartość była opcjonalna i tak naprawdę nie zastanawiałem się zbytnio, dlaczego może być zero lub jak właściwie poradzić sobie z tą sytuacją, ale dodanie !
sprawiło, że się skompilowała… więc mój kod jest poprawny, prawda?”
Strzeż się arogancji wykrzyknika. Zamiast…
3. Wykrzykniki najlepiej stosować oszczędnie.
Każda z tych !
konstrukcji ma ?
odpowiednik, który zmusza do radzenia sobie z przypadkiem błędu / zeru:
- Warunkowe rozpakowywanie:
if let name = nameLabel?.text { ... }
- Opcje:
var logo: UIImageView?
- Obsady warunkowe:
logo.image = thing as? UIImage
- Wyjątki od braku awarii:
try? NSJSONSerialization.JSONObjectWithData(data, [])
Jeśli masz ochotę na użycie !
, zawsze dobrze jest dokładnie rozważyć, dlaczego nie używasz ?
. Czy !
awaria programu jest naprawdę najlepszą opcją, jeśli operacja się nie powiedzie? Dlaczego ta wartość jest opcjonalna / nie działa?
Czy istnieje rozsądna ścieżka odzyskiwania, którą Twój kod może przyjąć w przypadku braku / błędu? Jeśli tak, koduj.
Jeśli nie może to być zero, jeśli błąd nigdy nie może się zdarzyć, to czy istnieje rozsądny sposób na poprawienie logiki, aby kompilator o tym wiedział? Jeśli tak, zrób to; twój kod będzie mniej podatny na błędy.
Są chwile, kiedy nie ma rozsądnego sposobu na poradzenie sobie z błędem, a po prostu zignorowanie błędu - a tym samym przejście do niewłaściwych danych - byłoby gorsze niż awaria. To są czasy, w których można użyć wymuszania rozpakowywania.
Okresowo przeszukuję całą bazę kodu !
i sprawdzam każde jej użycie. Bardzo niewiele zastosowań stoi do kontroli. (W chwili pisania tego tekstu cała platforma Siesta ma dokładnie dwa jej wystąpienia ).
Nie oznacza to, że nigdy nie powinieneś używać !
w swoim kodzie - po prostu powinieneś używać go ostrożnie i nigdy nie ustawiać go jako opcji domyślnej.