À l'aide d'un dispatch_once singleton modèle Swift

Je suis en train de mettre au point un singleton modèle pour l'utilisation de Swift. Jusqu'à présent, j'ai été en mesure d'obtenir un non-thread-safe modèle de travail:

class var sharedInstance:TPScopeManager {
    get {
        struct Static {
            static var instance : TPScopeManager? = nil
        }

        if !Static.instance {
            Static.instance = TPScopeManager()
        }

        return Static.instance!
    }
}

Habillage de l'instance du singleton dans la Statique de la structure doit permettre à une instance unique qui n'entrent pas en collision avec singleton instances sans complexe de nommage schemings, et il devrait rendre les choses assez privé. De toute évidence cependant, ce modèle n'est pas thread-safe, donc j'ai essayé d'ajouter dispatch_once à l'ensemble de la chose:

class var sharedInstance:TPScopeManager {
    get {
        struct Static {
            static var instance : TPScopeManager? = nil
            static var token : dispatch_once_t = 0
        }

        dispatch_once(Static.token) { Static.instance = TPScopeManager() }

        return Static.instance!
    }
}

Mais j'obtiens une erreur du compilateur sur la dispatch_once ligne:

Ne peut pas convertir l'expression est de type 'Void' type '()'

J'ai essayé plusieurs différentes variantes de la syntaxe, mais ils semblent tous avoir les mêmes résultats:

dispatch_once(Static.token, { Static.instance = TPScopeManager() })

Qu'est-ce que l'utilisation appropriée de dispatch_once l'utilisation de Swift? J'ai d'abord pensé que le problème était avec le bloc en raison de la () dans le message d'erreur, mais plus je la regarde, plus je pense que c'est peut être une question de la dispatch_once_t correctement défini.

Je voudrais supprimer tout ce qui statique de code et l'utilisation d'une propriété en lecture seule avec un @lazy initialiseur.
C'est ce que je voulais dire. Malheureusement, nous n'avons pas encore assez d'informations sur le fonctionnement interne. Cependant, à mon humble avis, la mise en œuvre des @lazy doit être thread-safe.
Et de cette façon, a aussi l'avantage de ne pas s'exposer à la mise en œuvre pour les prédateurs de les appelants.
Il ne semble pas que vous pouvez avoir @lazy variables de classe.
Attention! Deux choses sont à noter avec cette approche. Tout d'abord, toutes les classes qui héritent de ce qui aura pour remplacer le sharedInstance de la propriété. Static.instance = TPScopeManager() forces du type d'instance. Si vous utilisez quelque chose comme Static.instance = self() avec un initialiseur, le type approprié de la classe sera généré. Même si, et c'est la chose importante à noter, qu'une seule fois pour toutes les instances de la hiérarchie! Premier type d'initialiser le type est définie pour toutes les instances. Je ne pense pas que l'objective-c se comportaient de la même.

OriginalL'auteur David Berry | 2014-06-03