Para entender delegates
, tienes que entender protocols
.
A protocol
es como un contrato de servicio. Cuando un objeto (la mayoría de las veces una UIViewController
subclase, pero no siempre) firma ese contrato, dice "Estoy interesado en proporcionar lógica para respaldar el mensaje que me envía". Esto es similar a NSNotificationCenter
lo que respecta a registrarse para un nivel de interés, la diferencia es que un objeto que emplea delegación solo puede tener uno delegate
a la vez, donde varios objetos pueden registrarse para el mismo NSNotification
.
Apple usa la delegación de manera generalizada. Sin embargo, cada vez más, ves que Apple transfiere una gran parte de su API a blocks
, que son similares a callbacks
en otros idiomas.
Dicho esto, la delegación ayuda a mantener MVC, aunque yo diría que la delegación es un patrón de diseño en sí mismo. Ayuda a separar los modelos de los controladores. Tal como en el ejemplo de John Cartwright, a UITableView
sabe cómo mostrar filas y secciones. Sabe reutilizar UITableViewCells
por razones de rendimiento. Conoce todas las otras cosas que UIScrollView
sabe. Pero no sabe qué celdas mostrar. No sabe con qué poblar esas células. No sabe qué células reutilizar para un determinado NSIndexPath
. De todos modos, este debería ser el trabajo del controlador. La delegación permite que la vista de tabla descargue esta lógica de no vista en un objeto que de todos modos debería tener esa responsabilidad.
Más que eso, no estás encerrado en un delegado durante toda la vida de un objeto. Podría tener fácilmente múltiples fuentes de datos para un determinado UITableView
y cambiarlos en tiempo de ejecución según sea necesario.
Entonces, por un lado, la delegación es excelente para suministrar datos y responder a las interacciones de un objeto. Lo verá en un montón de clases UIKit, como un UITableView
, UIPickerView
, UICollectionView
, etc.
Pero la delegación también es muy útil cuando desea pasar información entre objetos. Puede crear fácilmente sus propios protocolos y registrar sus propios objetos para seguirlos. Además, los métodos de protocolo son @required
predeterminados, pero puede especificar algunos métodos para@optional
. Esto puede darle una buena flexibilidad si la necesita. Supongamos que tiene un controlador de vista principal y un controlador de vista secundario. Tal vez esté utilizando la nueva API de contención para hacer esto. Por lo general, si necesita pasar información del padre al hijo, debe hacerlo con una propiedad. Hecho. Pero, ¿qué sucede si necesita pasar información del niño a los padres? Tal vez algo cambie en el niño y necesite notificar a los padres. Claro, podrías hacer algo de KVO en ciertos valores. Pero tal vez quiera saber cuándo se presiona un botón. Simplemente cree un nuevo protocolo en el controlador de vista secundario
@protocol MyChildDelegate
- (void)buttonWasTappedInChild:(MyChildViewController *)childViewController;
@end
@interface MyChildViewController : UIViewController
@property (weak, nonatomic) id <MyChildDelegate> delegate;
@end
En MyChildViewController, cuando se toca el botón, simplemente verifique si su delegado responde al mensaje del delegado (si es necesario y su delegado no implementa el método, se bloqueará. Puede hacer el método @optional
si es necesario) y enviar eso:
- (IBAction)someButtonTapped:(id)sender {
if ([self.delegate respondsToSelector:@selector(buttonWasTappedInChild:)]) {
[self.delegate buttonWasTappedInChild:self];
}
}
Luego configure el delegado de su MyChildViewController self
e impleméntelo - (void)buttonWasTappedInChild:(MyChildViewController *)childViewController
en su controlador de vista principal. ¡AUGE! Tiene información transmitida de un niño a los padres. La relación entre los dos objetos ni siquiera necesita ser tan cercana como la principal / secundaria. Es un contrato de servicio, por lo tanto, siempre y cuando el objeto que se registre mantenga su parte del trato al implementar los métodos requeridos, ¡eres dorado!
NOTA: Los delegados deben ser débiles / asignar propiedades, de lo contrario, entrará en un ciclo de retención donde ninguno de los objetos puede ser desasignado.
¡Espero que esto ayude!