Swift kładzie duży nacisk na bezpieczeństwo typów. Cały język Swift został zaprojektowany z myślą o bezpieczeństwie. To jedna z cech charakterystycznych Swifta, którą należy powitać z otwartymi ramionami. Pomoże w opracowaniu czystego, czytelnego kodu i pomoże zapobiec awariom aplikacji.
Wszystkie opcje w Swift są oznaczone ?
symbolem. Ustawiając ?
po nazwie typu, w którym deklarujesz jako opcjonalny, zasadniczo rzutujesz to nie jako typ, w którym znajduje się przed ?
, ale zamiast tego jako typ opcjonalny .
Uwaga: zmienna lub typ Int
to nie to samo co Int?
. Są to dwa różne typy, które nie mogą działać na sobie nawzajem.
Korzystanie z opcjonalnego
var myString: String?
myString = "foobar"
Ten sposób nie oznacza, że użytkownik pracuje z typem String
. Oznacza to, że pracujesz z typem String?
(ciąg opcjonalny lub opcjonalny ciąg). W rzeczywistości za każdym razem, gdy spróbujesz
print(myString)
w czasie wykonywania wydrukuje konsola debugowania Optional("foobar")
. Część „ Optional()
” wskazuje, że ta zmienna może, ale nie musi, mieć wartość w czasie wykonywania, ale tak się składa, że obecnie zawiera ciąg „foobar”. To " Optional()
" wskazanie pozostanie, chyba że zrobisz tak zwane "" rozpakowywanie "opcjonalnej wartości.
Rozpakowanie opcjonalnego oznacza, że teraz rzutujesz ten typ jako nieopcjonalny. Spowoduje to wygenerowanie nowego typu i przypisanie wartości, która znajdowała się w tym opcjonalnym, do nowego nieopcjonalnego typu. W ten sposób można wykonywać operacje na tej zmiennej, ponieważ kompilator gwarantuje, że ma ona stałą wartość.
Warunkowe rozpakowanie sprawdzi, czy wartość w opcjonalnym jest, nil
czy nie. Jeśli tak nie jest nil
, pojawi się nowo utworzona stała zmienna, której zostanie przypisana wartość i zostanie rozpakowana do nieopcjonalnej stałej. A stamtąd możesz bezpiecznie używać nieopcjonalnego w if
bloku.
Uwaga: Stałej warunkowo nieopakowanej można nadać tę samą nazwę, co rozpakowywanej zmiennej opcjonalnej.
if let myString = myString {
print(myString)
// will print "foobar"
}
Warunkowe rozpakowanie opcji jest najczystszym sposobem uzyskania dostępu do wartości opcjonalnej, ponieważ jeśli zawiera ona wartość zerową, to wszystko w bloku if let nie zostanie wykonane. Oczywiście, tak jak w przypadku każdej instrukcji if, możesz dołączyć blok else
if let myString = myString {
print(myString)
// will print "foobar"
}
else {
print("No value")
}
Wymuszone rozpakowywanie odbywa się za pomocą tak zwanego !
operatora („bang”). Jest to mniej bezpieczne, ale nadal umożliwia kompilację kodu. Jednak za każdym razem, gdy używasz operatora bang, musisz mieć 1000% pewności, że zmienna faktycznie zawiera stałą wartość, zanim zostanie wymuszona rozpakowana.
var myString: String?
myString = "foobar"
print(myString!)
Powyższy kod jest całkowicie prawidłowym kodem Swift. Wyświetla wartość, myString
która została ustawiona jako „foobar”. Użytkownik zobaczy foobar
wydrukowany w konsoli i to wszystko. Ale załóżmy, że wartość nigdy nie została ustawiona:
var myString: String?
print(myString!)
Teraz mamy inną sytuację na naszych rękach. W przeciwieństwie do Objective-C, za każdym razem, gdy podejmowana jest próba wymuszonego rozpakowania opcjonalnego, a opcjonalny nie został ustawiony i jest nil
, gdy spróbujesz rozpakować opcjonalny, aby zobaczyć, co jest w środku, aplikacja ulegnie awarii.
Rozpakowywanie z rzutowaniem typów . Jak powiedzieliśmy wcześniej, chociaż jesteś unwrapping
opcjonalnym, w rzeczywistości rzutujesz na typ nieopcjonalny, możesz również rzutować nieopcjonalny na inny typ. Na przykład:
var something: Any?
Gdzieś w naszym kodzie zmienna something
otrzyma jakąś wartość. Może używamy leków generycznych, a może istnieje inna logika, która spowoduje zmianę tego. Więc później w naszym kodzie chcemy użyć, something
ale nadal możemy traktować go inaczej, jeśli jest to inny typ. W takim przypadku będziesz chciał użyć as
słowa kluczowego, aby to ustalić:
Uwaga: as
operator to sposób wpisywania rzutowania w języku Swift.
// Conditionally
if let thing = something as? Int {
print(thing) // 0
}
// Optionally
let thing = something as? Int
print(thing) // Optional(0)
// Forcibly
let thing = something as! Int
print(thing) // 0, if no exception is raised
Zwróć uwagę na różnicę między tymi dwoma as
słowami kluczowymi. Tak jak poprzednio, gdy siłą rozpakowaliśmy element opcjonalny, używaliśmy do tego !
operatora bang. Tutaj zrobisz to samo, ale zamiast rzucać jako nieobowiązkowe, rzucasz również jako Int
. I musi być możliwe do obniżenia, ponieważ Int
w przeciwnym razie, na przykład przy użyciu operatora bang, gdy wartością jest, nil
aplikacja ulegnie awarii.
Aby w ogóle użyć tych zmiennych w jakiejś operacji matematycznej, muszą zostać rozpakowane, aby to zrobić.
Na przykład w Swift tylko prawidłowe typy danych liczbowych tego samego rodzaju mogą być obsługiwane na sobie nawzajem. Kiedy rzucasz typ za pomocą as!
, wymuszasz obniżenie tej zmiennej, tak jakbyś był pewien, że jest tego typu, dlatego bezpieczna jest operacja i nie zawieszanie aplikacji. Jest to w porządku, o ile zmienna rzeczywiście jest typu, do którego ją rzucasz, w przeciwnym razie będziesz mieć bałagan na rękach.
Niemniej jednak rzutowanie za pomocą as!
pozwoli na kompilację kodu. Casting z an as?
to inna historia. W rzeczywistości as?
deklaruje razem Int
jako zupełnie inny typ danych.
Teraz jest Optional(0)
A jeśli kiedykolwiek próbowałeś odrobić pracę domową, pisząc coś takiego
1 + Optional(1) = 2
Twój nauczyciel matematyki prawdopodobnie dałby ci „F”. To samo z Swift. Tyle że Swift wolałby raczej w ogóle nie kompilować, niż wystawiać ocenę. Ponieważ pod koniec dnia opcja opcjonalna może w rzeczywistości być zerowa .
Bezpieczeństwo przede wszystkim.