Singleton mit Eigenschaften in Swift 3

88

In Apples Dokument " Verwenden von Swift mit Kakao und Objective-C" (aktualisiert für Swift 3) wird das folgende Beispiel für das Singleton-Muster angegeben:

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

        // setup code

        return instance
    }()
}

Stellen wir uns vor, dieser Singleton muss ein variables Array von Strings verwalten. Wie / wo würde ich diese Eigenschaft deklarieren und sicherstellen, dass sie ordnungsgemäß in einem leeren [String]Array initialisiert wird ?

Robert Joseph
quelle

Antworten:

236

Für mich ist dies der beste Weg, init privat zu machen. Schnelle 3 \ 4 \ 5-Syntax

// 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]()

}
YannSteph
quelle
4
Ich habe diese Antwort positiv bewertet, aber um der Swift 3-Syntax zu entsprechen, sollte "sharedInstance" in "shared" geändert werden.
B-Rad
1
Es sei denn, es gibt eine Regression von Swift 2 auf Swift 3, die Sie nicht tun
Thibaut Noah
1
Der Typ nach dem Teilen kann weggelassen werden, oder? static let shared = Singleton()
Chriswillow
1
@YannickSteph Sie müssen nicht schreiben, static let shared: Singleton = Singleton()stattdessen können Sie einfach schreibenstatic let shared = Singleton()
chriswillow
3
@RomanN Nein, Sie können init nicht überschreiben, da es keine Klasse erbt. Wenn Sie das können, mit diesem Beispiel final class Singleton: NSObject { private override init() { } }
YannSteph
59

Sie können ein leeres Array wie folgt initialisieren.

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
    }
}

Oder wenn Sie einen anderen Ansatz bevorzugen, ist dieser gut geeignet.

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
    }
}

quelle
Funktioniert diese Methode nicht in einer Erweiterung? extension Cache { static let sharedInstance: Cache = { let instance = Cache() return instance }() }
Andy
1
Interessant, dass Apple class varin iOS 10 für Singletons verwendet (zB UIApplication). Wäre ihre Implementierung dieselbe?
Jjatie
2
Ich bevorzuge Singleton-Init-Methoden als privateMethoden nicht einmal internal. Dies verhindert, dass andere Benutzer den Standardinitialisierer '()' für diese Klasse verwenden.
Kumar C
1
@ KumarC Sie sind richtig, würde es das Problem nicht lösen, wenn wir ein privateIn hinzufügen init.
@TikhonovAlexander Könnten Sie weitere Informationen mitbringen?
Dominique Vial
30

Gemäß der Apple-Dokumentation: In Swift können Sie einfach eine statische Typ-Eigenschaft verwenden, die garantiert nur einmal träge initialisiert wird, selbst wenn über mehrere Threads gleichzeitig zugegriffen wird .

class Singleton {

    // MARK: - Shared

    static let shared = Singleton()
}

Mit Initialisierungsmethode:

class Singleton {

    // MARK: - Shared

    static let shared = Singleton()

    // MARK: - Initializer

    private init() {
    }

}
Mehul Sojitra
quelle
3
Warum ist init () nicht privat?
XcodeNOOB
0

Jede Initialisierung würde in einer Init-Methode erfolgen. Kein Unterschied zwischen einem Singleton und einem Nicht-Singleton.

gnasher729
quelle
26
Ein zusätzliches Code-Snippet, das die Frage direkt beantwortet, würde diese Antwort hilfreicher machen.
Reda Lemeden