Geschrieben von Reinder de Vries am Januar 10 2019 in App-Entwicklung, Schnell

Ein Singleton ist eine Klasse, von der genau eine Instanz existiert, auf die global zugegriffen werden kann. Wie erstellt man einen Singleton in Swift? Und warum sollten oder sollten Sie nicht?

In diesem Tutorial werden wir uns mit Singletons in Swift befassen. Sie erfahren, was das Singleton-Entwurfsmuster ist und warum es nützlich ist. Wir werden die Syntax zum Erstellen von Singletons in Swift diskutieren. Und wir werden auf gute und schlechte Anwendungsfälle für Singletons eingehen.

Bereit? Lass uns gehen.

  1. Was ist ein Singleton?
  2. Singleton in Swift codieren
  3. Wann Singletons verwenden
  4. Weiterführende Literatur

Was ist ein Singleton?

Ein Singleton ist eine Klasse, von der nur eine Instanz existiert. Einige Beispiele:

  • Ein Unternehmen hat nur eine CEO
  • Eine API-Klasse hat nur eine serielle Anforderungswarteschlange
  • Ein Betriebssystem hat nur ein Dateisystem
  • Ein Sonnensystemkörper dreht sich um einen Gravitationspunkt
  • Eine App, die E / A ausführt, hat nur einen Standard FileManager
  • Ein Flugzeug hat nur ein Flugdeck

Das zweite Attribut eines Singleton ist, dass es einen globalen Zugangspunkt hat. Sie können auf einen Singleton zugreifen, zB. rufen Sie Funktionen von überall im Code Ihrer App auf.

Also, um es zusammenzufassen:

  1. Ein Singleton ist eine Klasse, die nur eine Instanz hat
  2. Auf sie kann global zugegriffen werden, dh überall in Ihrem Code

In der praktischen iOS-Entwicklung verwenden Sie häufig Singletons. Typische Klassen wie NotificationCenter, UserDefaults, SKPaymentQueue und FileManager haben shared oder default Eigenschaften, die Singletons sind.

Zu anderen Zeiten möchten Sie möglicherweise selbst einen Singleton erstellen. Ein guter Anwendungsfall ist eine API -Klasse, die eine Singleton-Instanz über ihre shared -Eigenschaft verfügbar macht. Sie verwenden API.shared.makeAPICall() , um über eine einzelne, einheitliche Instanz auf die API zuzugreifen. So können Sie beispielsweise API-Aufrufe seriell verwalten.

Bevor wir diskutieren, wann Singletons am besten verwendet werden (und wann nicht), wollen wir herausfinden, wie man einen Singleton in Swift codiert.

Als iOS-Entwickler eingestellt werden

Lernen Sie, iOS 14-Apps mit Swift 5 zu erstellen

Melden Sie sich für meinen iOS-Entwicklungskurs an und erfahren Sie, wie Sie Ihre Karriere als professioneller iOS-Entwickler beginnen können.

Codierung eines Singleton in Swift

Dies ist der beste Weg, um einen Singleton in Swift zu erstellen:

class API{ static let shared = API() private init() { // Set up API instance }}

Und so verwenden Sie den Singleton:

API.shared.doSomething()

Wir erstellen eine API -Klasse mit einer statischen Eigenschaft namens shared . Diese Eigenschaft kann nach dem Festlegen nicht geändert werden, da es sich um eine Konstante handelt, die statisch deklariert ist.

Das bedeutet, dass wir über die Klasse API auf die Eigenschaft shared zugreifen können. Dies wird oft als Klasseneigenschaft bezeichnet. Vergleichen Sie dies mit einer normalen Instanzeigenschaft, auf die nur über eine Instanz einer Klasse zugegriffen werden kann.

Interessant ist, dass die Eigenschaft shared eine Instanz von API innerhalb der Klasse API initialisiert. Wir erstellen eine Art API -Objekt, auf das über die API -Klasse zugegriffen werden kann. Aber es gibt noch mehr …

Der Klasseninitialisierer init() ist mit private markiert. Dieses private -Schlüsselwort stellt sicher, dass die API -Klasse nur innerhalb der API -Klasse initialisiert werden kann.

Mit anderen Worten, Sie können keine Instanz von API außerhalb der API -Klasse erstellen! Dies stellt sicher, dass das API Objekt, das wir erstellt haben, die einzige Instanz in unserem Code ist. Schließlich kann man nicht mehr davon schaffen.

Und jetzt haben wir sichergestellt, dass die API Klasse den beiden Attributen eines Singleton entspricht:

  1. Dank der statischen Eigenschaft shared kann global auf die API -Instanz zugegriffen werden
  2. Dank der private init() kann die API -Klasse nicht außerhalb der API -Klasse initialisiert werden

Dies alles mag für Sie etwas abstrakt klingen, erweitern wir also das vorherige Beispiel mit etwas praktischerem Code. Hier ist was:

Die API -Klasse ist größtenteils dieselbe. Es ist immer noch ein Singleton und verwendet immer noch diese static let shared = API() und private init() Codebits.

Hier ist, was sich geändert hat:

  • Die API -Klasse hat jetzt eine isRequestPending -Eigenschaft. Hier beginnt die Gefahr … Sehen Sie, wie der Boolesche Wert isRequestPending sicherstellt, dass jeweils nur eine API-Anforderung ausgeführt werden kann? (Beachten Sie, dass isRequestPending eine Instanzeigenschaft ist.)
  • Die API -Klasse hat auch eine makeAPIRequest() -Funktion. Stellen Sie sich vor, wir können diese Funktion verwenden, um einige Daten von einer Webservice-API wie der von Twitter zurückzuholen. In der Funktion können Sie sehen, dass eine Anfrage nur gestellt werden kann, wenn derzeit keine andere Anfrage aussteht.
  • Die API Klasse hat auch eine onReturnAPIRequest() Funktion. Diese Funktion wird aufgerufen, wenn die API-Anforderung zurückkehrt, d. H. Online-Daten in die App heruntergeladen wurden. Der Boolesche Wert isRequestPending wird erneut auf false gesetzt und die Anforderungsdaten werden verarbeitet.

Und so können wir den API Singleton überall in unserem Code verwenden:

API.shared.makeAPIRequest()

Wir müssen noch etwas besprechen. Die API -Klasse verwaltet jetzt etwas namens state . Du kannst „Zustand“ als ein Gefühl sehen: Du bist entweder glücklich oder du bist traurig oder du bist wütend und so weiter. Sie können von einem Zustand in den anderen wechseln.

Die API Klasse kann zwischen zwei Zuständen wechseln:

  • Ein Zustand, in dem isRequestPending false
  • Ein Zustand, in dem isRequestPending ist true

Wie Sie im nächsten Abschnitt erfahren werden, können State und Singletons Ihren Code verwüsten. Die schlechte Verwaltung des Zustands ist der Hauptgrund für den Missbrauch von Singleton.

Wann Singletons verwenden

Wann Singletons verwenden? Das Buch Design Patterns: Elemente wiederverwendbarer objektorientierter Software von The Gang of Four hat Folgendes zu sagen. Verwenden Sie das Singleton-Muster, wenn:

  • Es muss genau eine Instanz einer Klasse geben, auf die Clients von einem bekannten Zugriffspunkt aus zugreifen können müssen
  • Wenn die einzige Instanz durch Unterklassen erweiterbar sein sollte und Clients in der Lage sein sollten, eine erweiterte Instanz zu verwenden, ohne ihren Code zu ändern

Das ist komplex, aber worauf es ankommt, ist:

  • Verwenden Sie einen Singleton, wenn Ihr Code nicht mehr als eine Instanz einer Klasse erfordert (dh den CEO im Unternehmen)
  • Und wenn von überall in Ihrem Code darauf zugegriffen werden muss (dh., das Dateisystem)

Ein weiterer Anwendungsfall ist die Unterklasse. Eine globale Variable in Ihrem Code kann nicht einfach in Unterklassen unterteilt werden. Darüber hinaus können Singletons mithilfe der Abhängigkeitsinjektion komponententestet werden. Sie ersetzen die API -Instanz durch eine APIMock -Instanz und erhalten die Möglichkeit, API-Aufrufe zu testen, ohne die tatsächlichen Netzwerkanforderungen zu stellen.

Und wann benutzt du keine Singletons? Um diese Frage zu beantworten, müssen wir zu dem Staatsprinzip zurückkehren, das wir zuvor besprochen haben.

Eine häufige Falle für Anfänger von iOS-Entwicklern besteht darin, den Status und seine Abhängigkeiten schlecht zu verwalten. Stellen Sie sich vor, Sie erstellen eine App, die die API -Klasse verwendet, mit der wir zuvor gearbeitet haben.

Jedes Mal, wenn Sie die API-Klasse erweitern, fügen Sie immer mehr Eigenschaften hinzu, z:

  • Eine userID -Eigenschaft, die den angemeldeten Benutzer verfolgt, sobald der login() API-Aufruf erfolgt ist
  • Eine tweets -Eigenschaft mit Twitter-Daten, sobald der getTweets() -Aufruf erfolgt ist
  • Eine spinner -Eigenschaft mit einem UIActivityIndicatorView, die Sie einem View Controller hinzufügen, wenn eine Anforderung gestartet wurde

Dies macht zunächst sehr viel Sinn. Schließlich kann auf die Klasse API überall in Ihrem Code zugegriffen werden. Im Tweet View Controller können Sie also das Array API.shared.tweets und im Settings Controller userID , um der API schnell mitzuteilen, deren Einstellungen geändert werden sollen.

Leider ist Ihr Staat jetzt überall. Die API -Klasse hat Abhängigkeiten zu einer Reihe von Klassen, die nicht mit der einzelnen Verantwortung der API-Klasse zusammenhängen. Ihr Code ist zu einer Schüssel Spaghetti geworden, die sich alle verheddert haben. Der Code funktioniert möglicherweise einwandfrei, kann jedoch nicht gewartet und erweitert werden.

Schauen wir uns ein Beispiel an. Die onReturnAPIRequest() -Funktion, die wir zuvor definiert haben, steht kurz davor, eng gekoppelt zu werden …

Hier ist, was wir in Betracht ziehen:

  • Der onReturnAPIRequest() wird aufgerufen, wenn eine API-Webservice-Anforderung zurückgegeben wird, dh wenn Daten in die App gelangen. Diese Daten müssen irgendwohin gehen – zum Beispiel in einen Tweet View Controller. Wie übergeben Sie die Daten von API an den View Controller?
  • Eine offensichtliche Wahl besteht darin, einfach einen Verweis auf viewController in der Klasse API zu erstellen. Wenn die Daten eingehen, können Sie etwas wie viewController.tweets = tweetsData codieren. Dies ist leider eine schlechte Architektur, da jetzt API und der View Controller eng miteinander gekoppelt sind. Es ist unmöglich (oder schwer), Unit-Tests durchzuführen, und es kann zu Problemen kommen, wenn eine der beiden Klassen erweitert wird.
  • Es ist besser, einen Mechanismus zu wählen, der beide Klassen nicht fest miteinander verbindet. Eine Option wäre, einen Abschluss an onReturnAPIRequest() zu übergeben, der ausgeführt wird, wenn die Anforderung zurückkehrt. Dieser Verschluss kann dann Code enthalten, um die eingehenden Daten zu verarbeiten. Eine andere Möglichkeit wäre, NotificationCenter zu verwenden, um die Daten an den View Controller zu übergeben, oder eine Database -Klasse zu verwenden, um die Daten zu verarbeiten.

Das Singleton-Entwurfsmuster hat einige Kontroversen ausgelöst, einfach weil es leicht zu missbrauchen ist. Achten Sie bei der Verwendung von Singletons auf Status und Abhängigkeiten. Nur weil es einfach ist, globalen Zugriff auf den Staat zu haben, heißt das nicht, dass es eine gute Idee ist.

Als iOS-Entwickler eingestellt werden

Lernen Sie, iOS 14-Apps mit Swift 5 zu erstellen

Melden Sie sich für meinen iOS-Entwicklungskurs an und erfahren Sie, wie Sie Ihre Karriere als professioneller iOS-Entwickler beginnen können.

Weiterlesen

Und das ist alles! Singletons kennenzulernen ist ein lohnendes Ziel, besonders wenn Sie sich für App-Architektur und Systemdesign interessieren.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.