2012-10-08 24 views
19

Estoy creando un objeto que va a descargar cosas para todos mis controladores de vistas. El objeto es una instancia única y tiene un método de devolución de llamada con los datos recibidos una vez que se completa la descarga. También tiene una propiedad de delegado para que sepa a qué objeto devolver la llamada después de que se realice la descarga.Múltiples delegados en iOS

Existen varios controladores que usan esta instancia compartida, y mi pregunta es cómo devolver la llamada al controlador de vista correcto que solicitó la descarga.

Mi enfoque es usar la delegación, pero el problema es que dado que otros controladores de vista también son su delegado, el objeto de descarga podría devolver la llamada a cada objeto y esto será difícil de rastrear.

+2

¿Podría una solicitud para iniciar la descarga incluir un puntero al receptor de los datos? Entonces podría simplemente llamar al método de delegado en el receptor de cada solicitud. – user1118321

+0

Me encontré con un problema similar y encontré la solución lista https://github.com/aleph7/MultiDelegate –

Respuesta

42

He trabajado en proyectos donde las personas han intentado utilizar varios delegados y básicamente es una mala idea. El patrón delegado es una relación de 1 a 1 entre una clase y su delegado. Si bien es posible lograr cierto nivel de delegación múltiple mediante el cambio de entrada y salida de los delegados, es más probable que genere comportamientos y errores impredecibles.

Mi recomendación sería cambiar la forma en que está pensando en esto. Tiene dos opciones como lo veo:

  1. cambiar a un patrón Observer donde se puede registrar varios observadores, que la clase principal puede interactuar. Esto es útil cuando todos los observadores implementan el mismo protocolo y donde su clase principal quiere estar al tanto de los observadores y la interacción con ellos.

  2. Transmitir NSNotificaciones para indicar cambios de estado y eventos. Aquí hay un enfoque más desacoplado porque la clase principal no necesita saber quién está escuchando y no interactúa directamente con ellos. Otros pueden comenzar y dejar de recibir notificaciones en su tiempo libre. También tiene la ventaja de que no necesita crear o implementar un protocolo separado. En su lugar, registra las clases que necesita saber sobre los cambios con NSNotificationCenter que, a su vez, maneja todo el enrutamiento de las notificaciones por usted.

+3

Gracias por explicarme. NSNotification funcionó maravillosamente para mí. – guptron

+0

un poco tarde, pero para aquellos con problemas similares: consulte el patrón de editor/suscriptor – salocinx

10

De hecho, parece que el patrón delegado podría no ser el mejor enfoque aquí.

Me gustaría ver en NSNotificationCenter en su lugar.

La idea básica es que su singleton haciendo la conexión neta envía una notificación (con algo como postNotificationName:object:userInfo:), diciendo que hay nuevos datos disponibles. Dentro de esta notificación, puede pasar un objeto de diccionario (userInfo) que contiene los datos que ha obtenido, o información sobre qué partes de su Modelo contienen datos actualizados.

Luego, sus otros controladores de vista pueden registrarse para 'observar' estas notificaciones llamando al addObserver:selector:name:object:. En términos generales, cuando una vc se vuelve visible, llamo al addObserver, y al removeObserver cuando se oculta o se retira.

¡Buena suerte!

0

La delegación no parece la solución adecuada para este problema. ¿Qué tal si se requiere que el controlador de vista solicitante proporcione un objeto (uno mismo) y un selector para que usted llame como una notificación de finalización? Por supuesto, necesitará un lugar para almacenar ese objeto y selector hasta que finalice la descarga. Esperemos que tenga (o pueda crear) un objeto para esto.

+1

También podría usar los bloques de éxito. – fabb

0

Recomiendo el uso de una de estas maneras

observador:

cuando el uso de los datos que desea informar a otros objetos están cerca primitiva ones.for ejemplo, cuando se utiliza 'NSMutableArray' se no puede informar al cambio en uno de objeto por el patrón estándar implementado, al menos, es necesario implementar uno para su auto que no es reutilizable que gran parte

Notificación

cuando su interacción con el objeto de destino (los que necesitan ser informados) es unidireccional. Esto significa que no necesita ningún reconocimiento u otros datos de ellos.

delegado

cuando hay un objeto de informar en cada paso de tiempo.

nota: el uso de bloques para el éxito y fracasan no es un patrón para transmitir datos de su punto de cola de tareas cuando no se sabe cuando están terminando o en su defecto al igual que las operaciones de red

EDIT: how to create notification | multi delegate issues and implementation

0

Si bien estoy de acuerdo con la mayoría de las respuestas aquí, si de verdad desea lograr múltiples delegados, podría declarar un conjunto de delegados y enviar mensajes a todos los delegados dentro de esa matriz. Si su protocolo tiene métodos de delegado opcionales, compruebe con seguridad usando responds(to aSelector: Selector!) -> Bool antes de invocar (teniendo en cuenta la administración de la memoria, ya que se hará referencia a esos delegados en la matriz). Una vez más, estoy de acuerdo en que es probable que una gran cantidad de delegados sea una mala idea arquitectónica y que usar bloques o un centro de notificaciones se adapte mejor a sus necesidades.