2012-02-28 23 views
14

Tengo un NSObject que es un singleton. ¿Hay algún problema de tener un delegado para esta clase singleton? Me preocupa que falle para un tipo singleton.delegado para un objeto singleton

Aquí está mi situación. Tengo una función (dentro de esta clase singleton) que realiza una solicitud asíncrona para extraer un NSDictionary de una API. Básicamente, cuando se realiza esta solicitud, quiero notificar a una clase que la solicitud ha finalizado.

+2

¿Por qué un delegado fallaría? En su lugar, puede considerar utilizar 'NSNotificationCenter' para múltiples oyentes. –

+0

Solo tengo una clase que deseo notificar, actualicé el contexto de la pregunta también por encima de – adit

Respuesta

30

No, un delegado no fallaría, pero considerar el uso de NSNotificationCenter lugar:

static NSString *const kMyClassNotificationName = @"myClassNotificationName"; 

// where you would call a delegate method (e.g. [self.delegate doSomething]) 
[[NSNotificationCenter defaultCenter] postNotificationName:kMyClassNotificationName object:self userInfo: /* dictionary containing variables to pass to the delegate */]; 

// where you would set up a delegate (e.g. [Singleton instance].delegate = self) 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomething) name:kMyClassNotificationName object:[Singleton instance]]; 
+3

+1 para el 'NSNOtificationCenter' sugerido – HelmiB

+1

@adit Si necesita acelerar la búsqueda de observadores, puede usar una instancia especial de' NSNotificationCenter' en tu singleton En ese caso, solo haga que sea una propiedad de solo lectura de su singleton para que los observadores puedan registrarse directamente. – Costique

+3

Esto realmente es mala forma. ¿Por qué alguien deliberadamente podría picar el código de esta manera? Ver la respuesta de vikingosegundo para 2 mejores soluciones con un delegado o bloques – PostCodeism

17

Usted tiene básicamente tres opciones:

  • utilizar un delegado. Un singelton es un objeto, así que por supuesto puede tener un delegado. Si hay varios objetos que desean usarlo y necesitan establecerse como delegados, puede restablecerlos cada vez, pero eso puede ser complicado.

  • Use las notificaciones, como muestra Richard J. Ross III., Pero en serio: Me parece extraño, si tiene un singleton, que necesita informar a un delegado, pero usaría una tecnología de transmisión .

  • usan bloques de finalización, donde los objetos que llaman pasan un bloque al singleton, que se ejecuta, una vez que el singleton cumplió una tarea. Ver [NSURLConnection sendAsynchronousRequest:queue:completionHandler:] (vale, este no es un método singleton, sino un método de clase. El principio es el mismo), que usa un bloque de finalización, o el gran AFNetworking, que usa un bloque de éxito y de falla. De
    Es códigos de ejemplo:

    [[AFGowallaAPIClient sharedClient] getPath:urlString 
               parameters:mutableParameters 
                success:^(__unused AFHTTPRequestOperation 
                  *operation, 
                  id JSON) 
        { 
         NSMutableArray *mutableRecords = [NSMutableArray array]; 
         for (NSDictionary *attributes in [JSON valueForKeyPath:@"spots"]) { 
          Spot *spot = [[[Spot alloc] initWithAttributes:attributes] autorelease]; 
          [mutableRecords addObject:spot]; 
         } 
    
         if (block) { 
          block([NSArray arrayWithArray:mutableRecords]); 
         } 
        } failure:^(__unused AFHTTPRequestOperation *operation, NSError *error) { 
         if (block) { 
          block([NSArray array]); 
         } 
    }]; 
    
+3

Estimados revisores: La edición de una publicación para corregir errores tipográficos está bien y es muy útil. Pero agregar enlaces a bibliotecas que ni siquiera sé que no es así. – vikingosegundo

6

No hay nada malo en tener un delegado para un producto único, pero crea una gran cantidad de casos de borde que usted necesita para manejar. Tales como:

  • Si el objeto A llama setDelegate :, seguido inmediatamente por el objeto B setDelegate vocación: Un objeto entonces nunca va a recibir llamadas de delegado.

  • Debe comprobar si es el delegado antes de desactivar el delegado de singleton. Generalmente, en dealloc, llama al singleton.delegate = nil;. Si otro objeto pasó a ser delegado después de que lo hizo, entonces usted acaba de causar que inesperadamente deje de ser delegado.

Singletons con delegados no es un patrón bien establecido. Sus soluciones deben variar según cuán robusto sea su caso de uso. Aquí hay algunas soluciones (en orden de las más fáciles -> más robustas).

Debe ser sencillo

El diseño de su aplicación a múltiples objetos nunca han de ser delegado del Singleton, al mismo tiempo (esto puede ser imposible).

NSNotification

Uso NSNotificationCenter para señalar eventos en lugar de delegación. Vea algunas de las otras respuestas publicadas en este hilo.

múltiples delegados

Extender el producto único para apoyar delegado múltiple. setDelegate: sustituir con: addDelegate: y removeDelegate:

@property (atomic) NSMutableArray *delegates; 

- (void)addDelegate:(NSObject * <YourProtocol>)foo { 
    [self.delegates addObject:foo]; 
} 
- (void)removeDelegate:(NSObject * <YourProtocol>)foo { 
    [self.delegates removeObject:foo]; 
} 
- (void)signalDelegateEvent { 
    [self.delegates enumerateObjectsUsingBlock:^(id<YourProtocol> obj, 
               NSUInteger idx, 
               BOOL *stop) { 
     // call delegate method `foo` on each delegate 
     if ([obj respondsToSelector:@selector(foo)]) { 
      [obj foo]; 
     } 
    }]; 
} 

he utilizado el modelo multi-delegado con éxito en muchas aplicaciones. Tenga cuidado de pensar cómo multi-threading afecta las cosas si elige este enfoque.

+0

Nunca pensé en usar una solución de múltiples delegados, gracias por la idea. Es bueno tener en cuenta una variación del patrón de delegado – Chris

+0

¿Qué tal tener una devolución de llamada requerida para notificar a los delegados que van a ser reemplazados? – psobko

+1

Esta solución podría usar un NSSet en lugar de NSArray para recopilar delegados y asegurarse de que nada reciba mensajes múltiples. –

Cuestiones relacionadas