¿Qué es Delegación y por qué es importante en la programación de iOS?

11

En este momento me estoy enseñando a mí mismo la programación de iOS, y un concepto que me resulta muy difícil de entender es la delegación. ¿Qué es? ¿Por qué y cómo se usa? Cual es la ventaja? La escritura técnica del libro que estoy leyendo hace que sea difícil de entender.

DCIndieDev
fuente
44
Puede encontrar útil la intersección de etiquetas de delegados de C + en el desbordamiento de pila.

Respuestas:

16

Para entender delegates, tienes que entender protocols.

A protocoles como un contrato de servicio. Cuando un objeto (la mayoría de las veces una UIViewControllersubclase, 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 NSNotificationCenterlo que respecta a registrarse para un nivel de interés, la diferencia es que un objeto que emplea delegación solo puede tener uno delegatea 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 callbacksen 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 UITableViewsabe cómo mostrar filas y secciones. Sabe reutilizar UITableViewCellspor razones de rendimiento. Conoce todas las otras cosas que UIScrollViewsabe. 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 UITableViewy 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 @requiredpredeterminados, 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 @optionalsi 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 selfe impleméntelo - (void)buttonWasTappedInChild:(MyChildViewController *)childViewControlleren 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!

jmstone
fuente
2

Los delegados son objetos que implementan ciertas funciones cuando no tiene sentido implementar esas funciones en el objeto normal. Es una forma de inyección de dependencia.

Para un ejemplo concreto, mire el protocolo UITableViewDelegate. Estos métodos no tienen sentido para que una vista de tabla se implemente directamente, porque las acciones para seleccionar una fila de vista de tabla serán diferentes en cada aplicación y tal vez en cada vista de tabla. El delegado tiene un método -tableView:didSelectRowAtIndexPath:para que pueda crear un objeto que maneje la selección de filas sin subclasificar la vista de tabla para cada acción separada que desee implementar.

John Cartwright
fuente