Scritto da Reinder de Vries il gennaio 10 2019 in App Development, Swift

Un singleton è una classe di cui esiste esattamente un’istanza, a cui è possibile accedere globalmente. Come si crea un singleton in Swift? E perché dovresti o non dovresti?

In questo tutorial, ci immergeremo in singleton in Swift. Impari qual è il modello di progettazione singleton e perché è utile. Discuteremo la sintassi per la creazione di singleton in Swift. E entreremo in casi d’uso buoni e cattivi per i single.

Pronto? Andiamo.

  1. Che cos’è un Singleton?
  2. Codifica di un Singleton in Swift
  3. Quando usare Singleton
  4. Ulteriori letture

Che cos’è un Singleton?

Un singleton è una classe di cui esiste una sola istanza. Alcuni esempi:

  • Una società che ha un solo CEO
  • Una classe API è solo una serie di coda della richiesta
  • Un sistema operativo è solo un file di sistema
  • Un corpo del sistema solare ruota intorno a un punto intorno al
  • Un’app che fa I/O è solo uno di default FileManager
  • Un aereo ha un solo ponte di volo

Il secondo attributo di un singleton è che ha un punto di accesso. È possibile accedere a un singleton, ad es. chiama le funzioni su di esso, da qualsiasi punto del codice della tua app.

Quindi, per riassumere:

  1. Un singleton è una classe che ha una sola istanza
  2. È accessibile a livello globale, cioè ovunque nel tuo codice

Nello sviluppo pratico di iOS, usi spesso singleton. Classi tipiche come NotificationCenter, UserDefaults, SKPaymentQueue e FileManager hanno proprietà shared o default che sono singleton.

Altre volte, potresti voler creare un singleton tu stesso. Un buon caso d’uso è una classe API che espone l’istanza singleton tramite la sua proprietà shared. Si utilizza API.shared.makeAPICall() per accedere all’API tramite una singola istanza unificata. Ciò consente, ad esempio, di gestire le chiamate API in serie.

Prima di discutere quando i singleton vengono utilizzati al meglio (e quando no), scopriamo come codificare un singleton in Swift.

Vieni assunto come sviluppatore iOS

Impara a creare app iOS 14 con Swift 5

Iscriviti al mio corso di sviluppo iOS e scopri come iniziare la tua carriera come sviluppatore iOS professionista.

Codifica di un Singleton in Swift

Questo è il modo migliore per creare un singleton in Swift:

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

Ed ecco come si utilizza il singleton:

API.shared.doSomething()

Stiamo creando una classe APIche ha una proprietà statica chiamata shared. Questa proprietà non può essere modificata una volta impostata, perché è una costante ed è dichiarata staticamente.

Ciò significa che possiamo accedere alla proprietà shared tramite la classe API. Questo è spesso chiamato una proprietà di classe. Confrontalo con una normale proprietà di istanza, a cui è possibile accedere solo tramite un’istanza di una classe.

La cosa interessante è che la proprietà shared inizializza un’istanza di API all’interno della classe API. Stiamo creando un oggetto API a cui è possibile accedere tramite la classe API. Ma c’è di più

L’inizializzatore di classe init() è contrassegnato con private. Questa parola chiave private garantisce che la classe API possa essere inizializzata solo all’interno della classe API.

In altre parole, non è possibile creare un’istanza di API al di fuori della classe API! Ciò garantisce che l’oggetto API che abbiamo creato sia l’unica istanza nel nostro codice. Dopo tutto, non puoi crearne di più.

E ora abbiamo assicurato che la classe API è conforme ai due attributi di un singleton:

  1. Grazie alla proprietà statica shared, è possibile accedere globalmente all’istanza API
  2. Grazie a private init(), la classe API non può essere inizializzata al di fuori della classe API

Tutto ciò potrebbe sembrare un po ‘ astratto, quindi espandiamo l’esempio precedente con un codice più pratico. Ecco cosa:

La classe API è per lo più la stessa. È ancora un singleton e utilizza ancora quei bit di codice static let shared = API() e private init().

Ecco cosa è cambiato:

  • La classe API ora ha una proprietà isRequestPending. È qui che inizia il pericolo-Vedi come il booleano isRequestPending assicura che sia possibile eseguire solo una richiesta API alla volta? (Si noti che isRequestPending è una proprietà di istanza.)
  • La classe API ha anche una funzione makeAPIRequest(). Immagina di poter usare questa funzione per recuperare alcuni dati da un’API webservice, come quella di Twitter.Nella funzione, puoi vedere che una richiesta può essere fatta solo quando nessun’altra richiesta è attualmente in sospeso.
  • La classe API ha anche una funzione onReturnAPIRequest(). Questa funzione viene richiamata quando viene restituita la richiesta API, ovvero i dati online sono stati scaricati nell’app. Il booleano isRequestPending è impostato nuovamente su false e i dati della richiesta vengono elaborati.

Ed ecco come possiamo usare il singleton API ovunque nel nostro codice:

API.shared.makeAPIRequest()

C’e ‘ qualcos’altro di cui dobbiamo discutere. La classe API ora gestisce qualcosa chiamato stato. Puoi vedere “stato” come un sentimento: sei felice o sei triste, o sei arrabbiato, e così via. È possibile passare da uno stato all’altro.

La classe API può passare da due stati:

  • Uno stato in cui isRequestPending è false
  • Uno stato in cui isRequestPending è true

Come imparerai nella prossima sezione, state e singletons possono causare ogni sorta di caos sul tuo codice. Gestione dello stato male è il singolo più grande motivo per uso improprio singleton.

Quando usare i singleton

Quando usi i singleton? Il libro Design Patterns: Elements Of Reusable Object-Oriented Software by the Gang of Four ha quanto segue da dire. Utilizzare il modello singleton quando:

  • ci deve essere esattamente una istanza di una classe, e deve essere accessibile per i clienti di un noto punto di accesso
  • quando il sole istanza deve essere estensibile, con la creazione di sottoclassi, e i clienti devono essere in grado di utilizzare un esteso esempio, senza modificare il loro codice

Che è complesso, ma la cosa si riduce a è:

  • Utilizzare un singleton quando il codice non richiede più di una istanza di una classe (cioè, il CEO dell’azienda)
  • E quando deve essere accessibile da qualsiasi punto del codice (es., il file system)

Un altro caso d’uso è la sottoclasse. Una variabile globale nel tuo codice non può essere facilmente sottoclassata, ecco perché usi una classe singleton. Inoltre, i singleton possono essere testati in unità utilizzando dependency injection. Si sostituisce l’istanza API con un’istanza APIMock e si ottiene la possibilità di eseguire chiamate API di unit test senza effettuare le richieste di rete effettive.

E quando non usi i single? Per rispondere a questa domanda, dovremo tornare al principio dello stato di cui abbiamo discusso in precedenza.

Una trappola comune per gli sviluppatori iOS principianti è gestire male lo stato e le sue dipendenze. Immagina di creare un’app che utilizza la classe API con cui abbiamo lavorato in precedenza.

Ogni volta che si espande la classe API, si virano su sempre più proprietà, come ad esempio:

  • Una proprietà userID che tiene traccia dell’utente connesso, una volta effettuata la chiamata API login()
  • Una proprietà tweets con i dati di Twitter, una volta effettuata la chiamata getTweets()
  • Una proprietà spinner con un UIActivityIndicatorView che si aggiunge a un controller di visualizzazione quando è stata avviata una richiesta

All’inizio, questo ha molto senso da fare. Dopo tutto, è possibile accedere alla classe API in qualsiasi punto del codice. Quindi, nel Controller di visualizzazione Tweet è possibile utilizzare l’array API.shared.tweets e nel Controller delle impostazioni è possibile utilizzare userID per indicare rapidamente all’API le impostazioni da modificare.

Sfortunatamente, il tuo stato è ora dappertutto. La classe API ha dipendenze da un gruppo di classi che non sono correlate alla singola responsabilità della classe API. Il tuo codice è diventato una ciotola di spaghetti, tutto aggrovigliato. Il codice potrebbe funzionare bene, ma è impossibile mantenere ed estendere.

Diamo un’occhiata ad un esempio. La funzione onReturnAPIRequest() che abbiamo definito in precedenza è sull’orlo di diventare strettamente accoppiata –

Ecco cosa stiamo considerando:

  • onReturnAPIRequest() viene chiamato quando viene restituita una richiesta di webservice API, ovvero quando i dati entrano nell’app. Questi dati devono andare da qualche parte, ad esempio un controller di visualizzazione Tweet. Come si passano i dati da API al controller di visualizzazione?
  • Una scelta ovvia è semplicemente creare un riferimento a viewController nella classe API. Quando i dati arrivano, puoi codificare qualcosa come viewController.tweets = tweetsData. Questa è un’architettura povera, sfortunatamente, perché ora API e il controller di visualizzazione sono strettamente accoppiati. È impossibile (o difficile) testare l’unità e rischia di creare problemi quando si estende una delle due classi.
  • È meglio scegliere un meccanismo che non accoppi strettamente entrambe le classi. Un’opzione sarebbe quella di passare una chiusura a onReturnAPIRequest(), che viene eseguita quando la richiesta ritorna. Questa chiusura può quindi contenere codice per gestire i dati in arrivo. Un’altra opzione sarebbe quella di utilizzare NotificationCenter per passare i dati al controller di visualizzazione o utilizzare una classe Database per gestire i dati.

Il modello di progettazione singleton ha guadagnato qualche polemica, semplicemente perché è facile da abusare. Quando si utilizzano singleton, essere consapevoli dello stato e delle dipendenze. Solo perché è facile avere accesso globale allo stato, non significa che sia una buona idea.

Vieni assunto come sviluppatore iOS

Impara a creare app iOS 14 con Swift 5

Iscriviti al mio corso di sviluppo iOS e scopri come iniziare la tua carriera come sviluppatore iOS professionista.

Ulteriori letture

E questo è tutto quello che c’è da fare! Conoscere singletons è un obiettivo utile, soprattutto se sei interessato all’architettura delle app e alla progettazione dei sistemi.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.