Singleton con proprietà in Swift 3


88

Nel documento Using Swift with Cocoa and Objective-C di Apple (aggiornato per Swift 3) forniscono il seguente esempio del pattern Singleton:

class Singleton {
    static let sharedInstance: Singleton = {
        let instance = Singleton()

        // setup code

        return instance
    }()
}

Immaginiamo che questo singleton debba gestire un array variabile di stringhe. Come / dove dovrei dichiarare quella proprietà e assicurarmi che venga inizializzata correttamente su un [String]array vuoto ?

Risposte:


236

Per me questo è il modo migliore, rendere init privato. Sintassi rapida 3 \ 4 \ 5

// MARK: - Singleton

final class Singleton {

    // Can't init is singleton
    private init() { }

    // MARK: Shared Instance

    static let shared = Singleton()

    // MARK: Local Variable

    var emptyStringArray = [String]()

}

4
Ho votato positivamente questa risposta, ma per abbinare la sintassi di Swift 3, "sharedInstance" dovrebbe essere cambiato in "shared".
B-Rad

1
A meno che non ci sia una regressione da swift 2 a swift 3 non lo fai
thibaut noah

1
Il tipo dopo la condivisione può essere omesso, giusto? static let shared = Singleton()
chriswillow

1
@YannickSteph non devi scrivere static let shared: Singleton = Singleton()invece puoi semplicemente scriverestatic let shared = Singleton()
chriswillow

3
@RomanN No, non puoi sovrascrivere init perché non eredita una classe. Se puoi farlo, con questo esempio final class Singleton: NSObject { private override init() { } }
YannSteph,

59

Puoi inizializzare un array vuoto come questo.

class Singleton {

    //MARK: Shared Instance

    static let sharedInstance : Singleton = {
        let instance = Singleton(array: [])
        return instance
    }()

    //MARK: Local Variable

    var emptyStringArray : [String]

    //MARK: Init

    init( array : [String]) {
        emptyStringArray = array
    }
}

O se preferisci un approccio diverso, questo andrà bene.

class Singleton {

    //MARK: Shared Instance

    static let sharedInstance : Singleton = {
        let instance = Singleton()
        return instance
    }()

    //MARK: Local Variable

    var emptyStringArray : [String]? = nil

    //MARK: Init

    convenience init() {
        self.init(array : [])
    }

    //MARK: Init Array

    init( array : [String]) {
        emptyStringArray = array
    }
}

Questo metodo non funziona in un'estensione? extension Cache { static let sharedInstance: Cache = { let instance = Cache() return instance }() }
Andy,

1
Interessante che Apple utilizza class varin iOS 10 per i singleton (ad esempio, applicazione UIA). La loro implementazione sarebbe la stessa di questa?
jjatie

2
Preferisco metodi di inizializzazione singleton come privatemetodi nemmeno internal. Ciò impedisce ad altri di utilizzare l'inizializzatore predefinito "()" per questa classe.
Kumar C

1
@KumarC Lei ha ragione, non sarebbe risolvere il problema se si aggiunge una privatein init.

@TikhonovAlexander Potresti portare maggiori informazioni?
Dominique Vial

30

Secondo la documentazione della mela: in Swift, puoi semplicemente utilizzare una proprietà di tipo statico, che è garantito per essere inizializzata pigramente solo una volta, anche quando si accede simultaneamente a più thread .

class Singleton {

    // MARK: - Shared

    static let shared = Singleton()
}

Con metodo di inizializzazione:

class Singleton {

    // MARK: - Shared

    static let shared = Singleton()

    // MARK: - Initializer

    private init() {
    }

}

3
perché init () non è privato?
XcodeNOOB

0

Qualsiasi inizializzazione verrebbe eseguita in un metodo init. Nessuna differenza qui tra un singleton e un non singleton.


26
Uno snippet di codice aggiuntivo che risponde direttamente alla domanda renderebbe questa risposta più utile.
Reda Lemeden
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.