Próbuję wypracować odpowiedni model singletonu do użytku w Swift. Do tej pory udało mi się uzyskać bezpieczny dla wątków model działający jako:
class var sharedInstance: TPScopeManager {
get {
struct Static {
static var instance: TPScopeManager? = nil
}
if !Static.instance {
Static.instance = TPScopeManager()
}
return Static.instance!
}
}
Zawijanie instancji singletonowej w strukturze statycznej powinno pozwolić jednej instancji, która nie koliduje z instancjami singletonowymi bez skomplikowanych schematów nazewnictwa, i powinna uczynić to dość prywatnym. Oczywiście ten model nie jest bezpieczny dla wątków. Próbowałem więc dodać dispatch_once
do całości:
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!
}
}
Ale pojawia się błąd kompilatora w dispatch_once
wierszu:
Nie można przekonwertować typu wyrażenia „Void” na typ „()”
Wypróbowałem kilka różnych wariantów składni, ale wszystkie wydają się mieć takie same wyniki:
dispatch_once(Static.token, { Static.instance = TPScopeManager() })
Jakie jest właściwe użycie dispatch_once
Swift? Początkowo myślałem, że problem dotyczy bloku z powodu ()
komunikatu o błędzie, ale im dłużej na niego patrzę, tym bardziej myślę, że może to być kwestia dispatch_once_t
prawidłowego zdefiniowania.
@lazy
powinna być bezpieczna dla wątków.
Static.instance = TPScopeManager()
wymusza typ instancji. Jeśli użyjesz czegoś takiego Static.instance = self()
z wymaganym inicjatorem, zostanie wygenerowana odpowiednia klasa typu. Mimo to jest to ważna rzecz do odnotowania, tylko raz dla wszystkich instancji w hierarchii! Pierwszym typem do zainicjowania jest zestaw typów dla wszystkich instancji. Nie sądzę, żeby cel-c zachowywał się tak samo.