Singleton avec des propriétés à Swift 3

88

Dans le document Utilisation de Swift avec Cocoa et Objective-C d' Apple (mis à jour pour Swift 3), ils donnent l'exemple suivant du modèle Singleton:

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

        // setup code

        return instance
    }()
}

Imaginons que ce singleton ait besoin de gérer un tableau variable de Strings. Comment / où déclarer cette propriété et m'assurer qu'elle est correctement initialisée dans un [String]tableau vide ?

RobertJoseph
la source

Réponses:

236

Pour moi, c'est la meilleure façon de rendre init privé. Syntaxe Swift 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
la source
4
J'ai voté pour cette réponse, mais pour correspondre à la syntaxe Swift 3, "sharedInstance" devrait être changé en "shared".
B-Rad
1
À moins qu'il y ait une régression de Swift 2 à Swift 3, vous ne le faites pas
Thibaut Noah
1
Le type après partagé peut être omis, non? static let shared = Singleton()
chriswillow
1
@YannickSteph vous n'avez pas à écrire à la static let shared: Singleton = Singleton()place, vous pouvez simplement écrirestatic let shared = Singleton()
chriswillow
3
@RomanN Non, vous ne pouvez pas remplacer init car il n'hérite pas d'une classe. Si vous pouvez le faire, avec cet exemple final class Singleton: NSObject { private override init() { } }
YannSteph
59

Vous pouvez initialiser un tableau vide comme celui-ci.

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

Ou si vous préférez une approche différente, celle-ci fera l'affaire.

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

la source
Cette méthode ne fonctionne-t-elle pas dans une extension? extension Cache { static let sharedInstance: Cache = { let instance = Cache() return instance }() }
Andy
1
Intéressant qu'Apple utilise class vardans iOS 10 pour les singletons (par exemple UIApplication). Leur mise en œuvre serait-elle la même que celle-ci?
jjatie
2
Je préfère les méthodes init singleton comme privateméthodes même pas internal. Cela empêche les autres d'utiliser l'initialiseur par défaut '()' pour cette classe.
Kumar C
1
@KumarC Vous avez raison, ne serait - il résoudre le problème si l' on ajoute un privatedans init.
@TikhonovAlexander Pouvez-vous nous apporter plus d'informations?
Dominique Vial
30

Selon la documentation d'Apple: dans Swift, vous pouvez simplement utiliser une propriété de type statique, qui est garantie d'être initialisée paresseusement une seule fois, même en cas d'accès simultané sur plusieurs threads .

class Singleton {

    // MARK: - Shared

    static let shared = Singleton()
}

Avec la méthode d'initialisation:

class Singleton {

    // MARK: - Shared

    static let shared = Singleton()

    // MARK: - Initializer

    private init() {
    }

}
Mehul Sojitra
la source
3
pourquoi init () n'est pas privé?
XcodeNOOB
0

Toute initialisation serait effectuée dans une méthode init. Aucune différence ici entre un singleton et un non-singleton.

gnasher729
la source
26
Un extrait de code supplémentaire qui répond directement à la question rendrait cette réponse plus utile.
Reda Lemeden