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.

  1. Co To Jest Singleton?
  2. Kodowanie Singletonu W Języku Swift
  3. Kiedy Używać Singletonów
  4. 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:

  1. singleton jest klasą, która ma tylko jedną instancję
  2. 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:

  1. dzięki właściwości statycznejshared, instancja APImoże być dostępna globalnie
  2. 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ść logiczna isRequestPending zapewnia, że można wykonać tylko jedno żądanie API naraz? (Zauważ, że isRequestPending 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ść logiczna isRequestPending jest ponownie ustawiona na false, 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 jest false
  • stan, w którym isRequestPending jest true

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 API login()
  • a tweets właściwość z danymi Twittera, po wykonaniu wywołania getTweets()
  • a spinner właściwość z UIActivityIndicatorView, którą dodajesz do kontrolera widoku po rozpoczęciu żądania

na początku ma to sens. W końcu Klasa APImoż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 z API do kontrolera widoków?
  • oczywistym wyborem jest po prostu utworzenie odniesienia do viewController w klasie API. Gdy pojawią się DANE, możesz zakodować coś w stylu viewController.tweets = tweetsData. Niestety jest to słaba Architektura, ponieważ teraz API 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życie NotificationCenter do przekazania danych do kontrolera widoku lub użycie klasy Database 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.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.