Si puede apuntar a iOS 4.0 o superior
Usando GCD, ¿es la mejor manera de crear singleton en Objective-C (hilo seguro)?
+ (instancetype)sharedInstance
{
static dispatch_once_t once;
static id sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
instancetype
. La finalización del código es mucho mejor cuando se usa eso en lugar deid
.Respuestas:
Esta es una manera perfectamente aceptable y segura para crear una instancia de su clase. Puede que técnicamente no sea un "singleton" (en el sentido de que solo puede haber 1 de estos objetos), pero siempre que solo use el
[Foo sharedFoo]
método para acceder al objeto, esto es lo suficientemente bueno.fuente
tipo de instancia
instancetype
es solo una de las muchas extensiones de idiomaObjective-C
, y se agregan más con cada nueva versión.Conócelo, ámalo.
Y tómelo como un ejemplo de cómo prestar atención a los detalles de bajo nivel puede brindarle información sobre nuevas y poderosas formas de transformar Objective-C.
Consulte aquí: tipo de instancia
fuente
MySingleton.h
MySingleton.m
fuente
init
?MySingleton
, por ejemplo, en queMySingleton.m
estoy llamando[super alloc]
Puede evitar que la clase se asigne sobrescribiendo el método de asignación.
fuente
Dave tiene razón, eso está perfectamente bien. Es posible que desee consultar los documentos de Apple sobre cómo crear un singleton para obtener consejos sobre la implementación de algunos de los otros métodos para garantizar que solo se pueda crear uno si las clases eligen NO usar el método sharedFoo.
fuente
Si desea asegurarse de que [[MyClass alloc] init] devuelve el mismo objeto que sharedInstance (no es necesario en mi opinión, pero algunas personas lo quieren), eso se puede hacer de manera muy fácil y segura usando un segundo dispatch_once:
Esto permite que cualquier combinación de [[MyClass alloc] init] y [MyClass sharedInstance] devuelva el mismo objeto; [MyClass sharedInstance] sería un poco más eficiente. Cómo funciona: [MyClass sharedInstance] llamará [[MyClass alloc] init] una vez. Otro código podría llamarlo también, cualquier cantidad de veces. La primera persona que llama a init hará la inicialización "normal" y almacenará el objeto singleton en el método init. Cualquier llamada posterior a init ignorará por completo qué asignación devolvió y devolverá la misma SharedInstance; El resultado de alloc será desasignado.
El método + sharedInstance funcionará como siempre. Si no es la primera persona que llama en llamar a [[MyClass alloc] init], entonces el resultado de init no es el resultado de la llamada de asignación, pero eso está bien.
fuente
Pregunta si esta es la "mejor manera de crear singleton".
Algunas reflexiones:
Primero, sí, esta es una solución segura para subprocesos. Este
dispatch_once
patrón es la forma moderna y segura de subprocesos para generar tonos únicos en Objective-C. No te preocupes allí.Sin embargo, usted preguntó si esta es la "mejor" forma de hacerlo. Sin embargo, uno debería reconocer que el
instancetype
y[[self alloc] init]
es potencialmente engañoso cuando se usa junto con singletons.El beneficio
instancetype
es que es una forma inequívoca de declarar que la clase puede subclasificarse sin recurrir a un tipo deid
, como teníamos que hacer en el pasado.Pero
static
en este método presenta desafíos de subclases. ¿Qué pasaría siImageCache
y losBlobCache
singletons fueran ambas subclases de unaCache
superclase sin implementar su propiosharedCache
método?Para que esto funcione, debe asegurarse de que las subclases implementen su propio
sharedInstance
método (o como lo llame para su clase particular).En pocas palabras,
sharedInstance
parece que su original admitirá subclases, pero no lo hará. Si tiene la intención de admitir subclases, al menos incluya documentación que advierta a los futuros desarrolladores que deben anular este método.Para una mejor interoperabilidad con Swift, probablemente desee definir esto como una propiedad, no un método de clase, por ejemplo:
Luego puede continuar y escribir un captador para esta propiedad (la implementación usaría el
dispatch_once
patrón que sugirió):El beneficio de esto es que si un usuario de Swift va a usarlo, haría algo como:
Tenga en cuenta que no hay
()
, porque lo implementamos como una propiedad. Iniciando Swift 3, así es como generalmente se accede a los singletons. Por lo tanto, definirlo como una propiedad ayuda a facilitar esa interoperabilidad.Además, si observa cómo Apple está definiendo sus singletons, este es el patrón que han adoptado, por ejemplo, su
NSURLSession
singleton se define de la siguiente manera:Otra consideración de interoperabilidad Swift muy menor fue el nombre del singleton. Es mejor si puede incorporar el nombre del tipo, en lugar de
sharedInstance
. Por ejemplo, si la clase eraFoo
, podría definir la propiedad singleton comosharedFoo
. O si la clase fueraDatabaseManager
, podría llamar a la propiedadsharedManager
. Entonces los usuarios de Swift podrían hacer:Claramente, si realmente desea usar
sharedInstance
, siempre puede declarar el nombre de Swift si desea:Claramente, al escribir código Objective-C, no debemos permitir que la interoperabilidad de Swift supere otras consideraciones de diseño, pero aún así, si podemos escribir código que admita ambos lenguajes con gracia, es preferible.
Estoy de acuerdo con otros que señalan que si quieres que esto sea un verdadero singleton donde los desarrolladores no pueden / no deben (accidentalmente) crear instancias de sus propias instancias, el
unavailable
calificador está activadoinit
ynew
es prudente.fuente
Para crear singleton seguro para subprocesos puede hacer lo siguiente:
y este blog explica singleton muy bien singletons en objc / cocoa
fuente
fuente
fuente