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 Intto 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, nilczy 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 ifbloku.
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ść, myStringktóra została ustawiona jako „foobar”. Użytkownik zobaczy foobarwydrukowany 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ś unwrappingopcjonalnym, 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 somethingotrzyma 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ć, somethingale nadal możemy traktować go inaczej, jeśli jest to inny typ. W takim przypadku będziesz chciał użyć assłowa kluczowego, aby to ustalić:
Uwaga: asoperator 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 assł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ż Intw przeciwnym razie, na przykład przy użyciu operatora bang, gdy wartością jest, nilaplikacja 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 Intjako 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.