napisany przez Reinder de Vries na styczeń 10 2019 w rozwój aplikacji, Swift
singleton jest klasą, w której istnieje dokładnie jedna instancja, która może być dostępna globalnie. Jak stworzyć singleton w Swift? A dlaczego powinieneś, a nie powinieneś?
w tym samouczku zajmiemy się singletonami w języku Swift. Dowiesz się, czym jest wzorzec projektowy singleton i dlaczego jest przydatny. Omówimy składnię tworzenia singletonów w języku Swift. I przejdziemy do dobrych i złych przypadków użycia singletonów.
gotowy? Chodźmy.
- Co To Jest Singleton?
- Kodowanie Singletonu W Języku Swift
- Kiedy Używać Singletonów
- Czytaj Dalej
Co To Jest Singleton?
singleton jest klasą, której istnieje tylko jedna instancja. Kilka przykładów:
- firma ma tylko jeden
CEO
- Klasa API ma tylko jedną kolejkę żądań szeregowych
- System operacyjny ma tylko jeden system plików
- ciało układu słonecznego obraca się wokół jednego punktu grawitacyjnego
- aplikacja wykonująca operacje We/Wy ma tylko jeden domyślny
FileManager
- samolot ma tylko jeden pokład
drugim atrybutem Singletona jest to, że ma globalny punkt dostępu. Możesz uzyskać dostęp do singletonu, np. funkcje połączeń na nim, z dowolnego miejsca w kodzie aplikacji.
tak więc podsumowując:
- singleton jest klasą, która ma tylko jedną instancję
- można do niej uzyskać dostęp globalnie, tj. gdziekolwiek w kodzie
w praktycznym rozwoju iOS często używasz singletonów. Typowe klasy jak NotificationCenter
, UserDefaults
, SKPaymentQueue
i FileManager
mają shared
lub default
właściwości, które są singletami.
w innym czasie możesz sam stworzyć singleton. Dobrym przykładem użycia jest klasa API
, która eksponuje instancję Singletona poprzez swoją właściwość shared
. Używasz API.shared.makeAPICall()
, aby uzyskać dostęp do interfejsu API za pośrednictwem jednej, zunifikowanej instancji. Pozwala to na przykład na seryjne zarządzanie wywołaniami API.
zanim omówimy, kiedy najlepiej używać singletonów (a kiedy nie), dowiedzmy się, jak kodować singleton w języku Swift.
Zostań programistą iOS
Naucz się tworzyć aplikacje na iOS 14 za pomocą Swift 5
Zapisz się na mój kurs rozwoju iOS i dowiedz się, jak rozpocząć karierę jako profesjonalny programista iOS.
kodowanie Singletona w języku Swift
jest to najlepszy sposób na stworzenie Singletona w języku Swift:
class API{ static let shared = API() private init() { // Set up API instance }}
a oto jak korzystasz z Singletona:
API.shared.doSomething()
tworzymy klasę API
, która ma jedną statyczną właściwość o nazwie shared
. Ta właściwość nie może być zmieniona raz ustawiona, ponieważ jest stała i jest zadeklarowana statycznie.
oznacza to, że możemy uzyskać dostęp do właściwości shared
poprzez klasę API
. Jest to często nazywane właściwością klasy. Porównaj to z właściwością zwykłej instancji, do której można uzyskać dostęp tylko przez instancję klasy.
co ciekawe, właściwość shared
inicjalizuje instancję API
wewnątrz klasy API
. Tworzymy obiekt API
, do którego można uzyskać dostęp poprzez klasę API
. Ale jest więcej …
inicjalizator klasy init()
jest oznaczony private
. To słowo kluczowe private
zapewnia, że Klasa API
może być inicjowana tylko wewnątrz klasy API
.
innymi słowy, nie możesz utworzyć instancji API
poza klasą API
! Zapewnia to, że obiekt API
, który stworzyliśmy, jest jedyną instancją w naszym kodzie. Po tym wszystkim, nie można stworzyć więcej.
i teraz upewniliśmy się, że Klasa API
jest zgodna z dwoma atrybutami Singletona:
- dzięki właściwości statycznej
shared
, instancjaAPI
może być dostępna globalnie - dzięki
private init()
, KlasaAPI
nie może być zainicjalizowana poza klasąAPI
to wszystko może brzmieć dla ciebie trochę abstrakcyjnie, więc rozwińmy poprzedni przykład o bardziej praktyczny kod. Oto co:
Klasa API
jest w większości taka sama. Nadal jest singletonem i nadal używa tych static let shared = API()
i private init()
bitów kodu.
oto co się zmieniło:
- Klasa
API
ma teraz właściwośćisRequestPending
. Tutaj zaczyna się niebezpieczeństwo… widzisz, jak wartość logicznaisRequestPending
zapewnia, że można wykonać tylko jedno żądanie API naraz? (Zauważ, żeisRequestPending
jest właściwością instancji. - Klasa
API
ma również funkcjęmakeAPIRequest()
. Wyobraźmy sobie, że możemy użyć tej funkcji, aby odzyskać dane z API webservice, takiego jak Twitter. w tej funkcji możesz zobaczyć, że żądanie może zostać złożone tylko wtedy, gdy żadne inne żądanie nie jest obecnie oczekujące. - Klasa
API
ma również funkcjęonReturnAPIRequest()
. Funkcja ta jest wywoływana po powrocie żądania API, tzn. dane online zostały pobrane do aplikacji. Wartość logicznaisRequestPending
jest ponownie ustawiona nafalse
, a dane żądania są przetwarzane.
i oto jak możemy użyć API
Singletona w dowolnym miejscu naszego kodu:
API.shared.makeAPIRequest()
jest coś jeszcze, o czym musimy porozmawiać. Klasa API
zarządza teraz czymś zwanym stanem. Możesz postrzegać „stan” jako uczucie: jesteś albo szczęśliwy, albo smutny, albo zły, i tak dalej. Możesz przełączyć się z jednego stanu na drugi.
Klasa API
może przełączać się między dwoma stanami:
- stan, w którym
isRequestPending
jestfalse
- stan, w którym
isRequestPending
jesttrue
jak dowiesz się w następnej sekcji, Stan i singletony mogą siać różnego rodzaju spustoszenie w Twoim kodzie. Kiepskie zarządzanie stanem jest największym powodem nadużycia Singletona.
kiedy używać singletonów
kiedy używać singletonów? Książka Design Patterns: Elements of Reusable Object-Oriented Software by the Gang of Four ma do powiedzenia co następuje. Użyj wzoru Singletona, gdy:
- musi istnieć dokładnie jedna instancja klasy I musi ona być dostępna dla klientów z dobrze znanego punktu dostępu
- , kiedy jedyna instancja powinna być rozszerzalna przez podklasowanie, a klienci powinni móc używać instancji rozszerzonej bez modyfikowania ich kodu
to jest skomplikowane, ale sprowadza się do tego, że:
- używaj Singletona, gdy twój kod wymaga nie więcej niż jednej instancji klasy (np. CEO w firmie)
- i gdy musi być dostępny z dowolnego miejsca w kodzie (np., system plików)
innym przypadkiem użycia jest podklasowanie. Zmienna globalna w kodzie nie może być łatwo podklasyfikowana, dlatego używasz klasy singleton. Dodatkowo singletony mogą być testowane jednostkowo za pomocą iniekcji zależności. Zastępujesz wystąpienie API
wystąpieniem APIMock
i zyskujesz możliwość jednostkowego testowania wywołań API bez wykonywania rzeczywistych żądań sieciowych.
a kiedy nie używasz singletonów? Aby odpowiedzieć na to pytanie, musimy wrócić do zasady stanu, o której mówiliśmy wcześniej.
częstą pułapką dla początkujących programistów iOS jest złe zarządzanie stanem i jego zależnościami. Wyobraź sobie, że tworzysz aplikację, która używa klasy API
, z którą pracowaliśmy wcześniej.
za każdym razem, gdy rozszerzasz klasę API, korzystasz z coraz większej liczby właściwości, takich jak:
- a
userID
właściwość, która śledzi zalogowanego użytkownika, po wykonaniu wywołania APIlogin()
- a
tweets
właściwość z danymi Twittera, po wykonaniu wywołaniagetTweets()
- a
spinner
właściwość zUIActivityIndicatorView
, którą dodajesz do kontrolera widoku po rozpoczęciu żądania
na początku ma to sens. W końcu Klasa API
może być dostępna w dowolnym miejscu w kodzie. Tak więc w kontrolerze widoku Tweet możesz użyć tablicy API.shared.tweets
, a w kontrolerze ustawień możesz użyć userID
, aby szybko powiedzieć API, których ustawienia mają się zmienić.
niestety, twój stan jest teraz wszędzie. Klasa API
ma zależności do kilku klas, które nie są powiązane z pojedynczą odpowiedzialnością klasy API. Twój kod stał się miską spaghetti, zaplątaną. Kod może działać dobrze, ale nie da się go utrzymać i rozszerzyć.
spójrzmy na przykład. Funkcja onReturnAPIRequest()
, którą zdefiniowaliśmy wcześniej, znajduje się na skraju ścisłego sprzężenia …
oto, co rozważamy:
-
onReturnAPIRequest()
jest wywoływany, gdy żądanie webservice API powraca, tj. gdy dane przychodzą do aplikacji. Te dane muszą gdzieś pójść – na przykład kontroler widoku tweeta. Jak przekazać dane zAPI
do kontrolera widoków? - oczywistym wyborem jest po prostu utworzenie odniesienia do
viewController
w klasieAPI
. Gdy pojawią się DANE, możesz zakodować coś w styluviewController.tweets = tweetsData
. Niestety jest to słaba Architektura, ponieważ terazAPI
i kontroler widoku są ściśle ze sobą powiązane. Test jednostkowy jest niemożliwy (lub trudny) i może powodować problemy podczas rozszerzania obu klas. - lepiej wybrać mechanizm, który nie sparuje obu klas. Jedną z opcji byłoby przekazanie zamknięcia do
onReturnAPIRequest()
, które jest wykonywane po powrocie żądania. To zamknięcie może zawierać kod do obsługi przychodzących danych. Inną opcją byłoby użycieNotificationCenter
do przekazania danych do kontrolera widoku lub użycie klasyDatabase
do obsługi danych.
wzorzec projektowy Singletona zyskał pewne kontrowersje, po prostu dlatego, że łatwo go nadużywać. Podczas korzystania z singletonów należy pamiętać o stanie i zależnościach. To, że łatwo jest mieć globalny dostęp do państwa, nie oznacza, że jest to dobry pomysł.
Zostań programistą iOS
Naucz się tworzyć aplikacje na iOS 14 za pomocą Swift 5
Zapisz się na mój kurs rozwoju iOS i dowiedz się, jak rozpocząć karierę jako profesjonalny programista iOS.
Czytaj dalej
i to wszystko! Poznanie singletonów to wartościowy cel, zwłaszcza jeśli interesuje Cię Architektura aplikacji i Projektowanie systemów.