Singleton z właściwościami w Swift 3

88

W dokumencie Apple Using Swift with Cocoa and Objective-C (zaktualizowanym dla Swift 3) podają następujący przykład wzorca Singleton:

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

        // setup code

        return instance
    }()
}

Wyobraźmy sobie, że ten singleton musi zarządzać zmienną tablicą ciągów. Jak / gdzie miałbym zadeklarować tę właściwość i upewnić się, że zostanie poprawnie zainicjowany w pustej [String]tablicy?

RobertJoseph
źródło

Odpowiedzi:

236

Dla mnie to najlepszy sposób, aby init był prywatny. Szybka składnia 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]()

}
YannSteph
źródło
4
Głosowałem za tą odpowiedzią, ale aby dopasować składnię Swift 3, „sharedInstance” należy zmienić na „shared”.
B-Rad
1
O ile nie ma regresji ze Swift 2 do Swift 3, nie możesz
thibaut noah
1
Typ po udostępnieniu można pominąć, prawda? static let shared = Singleton()
chriswillow
1
@YannickSteph nie musisz pisać static let shared: Singleton = Singleton()zamiast tego możesz po prostu napisaćstatic let shared = Singleton()
chriswillow
3
@RomanN Nie, nie możesz zastąpić init, ponieważ nie dziedziczy on klasy. Jeśli możesz to zrobić, na tym przykładzie final class Singleton: NSObject { private override init() { } }
YannSteph
59

Możesz zainicjować pustą tablicę w ten sposób.

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

Lub jeśli wolisz inne podejście, to wystarczy.

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

źródło
Czy ta metoda nie działa w rozszerzeniu? extension Cache { static let sharedInstance: Cache = { let instance = Cache() return instance }() }
Andrew,
1
Ciekawe, że Apple używa class varw iOS 10 dla singletonów (np. UIApplication). Czy ich realizacja byłaby taka sama?
jjatie
2
Wolę metody singleton init, a privatenie metody internal. Zapobiega to używaniu przez inne osoby domyślnego inicjatora „()” dla tej klasy.
Kumar C
1
@KumarC Jesteś poprawne, czy nie rozwiąże problemu, jeśli dodamy privatew init.
@TikhonovAlexander Czy możesz przynieść więcej informacji?
Dominique Vial
0

Każda inicjalizacja byłaby wykonywana metodą init. Nie ma różnicy między singletonem a nie-singletonem.

gnasher729
źródło
26
Dodatkowy fragment kodu, który bezpośrednio odpowiada na pytanie, uczyniłby tę odpowiedź bardziej przydatną.
Reda Lemeden