¿Dónde coloco los métodos delegados y cómo los invoco?

Como nuevo desarrollador de iOS, finalmente me encontré con delegados. Estoy tratando de seguir un tutorial: http://gabriel-tips.blogspot.com/2011/05/input-accessory-view-how-to-add-extra.html, pero tengo dificultades para entender dónde se supone que debo colocar los métodos de delegado reales.

En segundo lugar, ¿a alguien le importaría proporcionar una explicación simplificada de cómo se invoca un método de delegado?

¡Gracias!

preguntado el 22 de mayo de 12 a las 21:05

3 Respuestas

Un delegado es simplemente una clase que accede a trabajar para otra clase. Los métodos delegados son invocados por la clase delegante. Por lo tanto, el delegado debe proporcionar una implementación del método apropiado. Hagamos un controlador de vista simple con una vista de tabla.

// MyViewController.h
@interface MyViewController : UIViewController <UITableViewDelegate>
@property (nonatomic, retain) UITableView *myTableView;
@end

Aquí, en el archivo MyViewController.h, he declarado que mi controlador de vista es un delegado de tipo UITableViewDelegate (realmente significa que implementa el protocolo UITableViewDelegate. Más sobre esto más adelante). Por lo tanto, he aceptado responder a las solicitudes de mi controlador de vista. Las solicitudes provendrán de la vista de tabla denominada myTableView. Sin embargo, simplemente afirmar que me adhiero a UITableViewDelegate no convierte a mi controlador de vista en un delegado de nada. Debo especificar eso directamente:

// MyViewController.m
#import "MyViewController.h"

@implementation MyViewController

- (void)loadView
{
    myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
    myTableView.delegate = self;
    self.view = myTableView;
}

@end

Aquí configuro específicamente MyViewController para que sea el delegado de myTableView. Ahora, cada vez que la vista de la tabla quiera pedirle a su delegado que haga algo, enviará ese mensaje a mi controlador de vista. Por lo tanto, MyViewController DEBE proporcionar implementaciones de los métodos de delegado apropiados:

// MyViewController.m
#import "MyViewController.h"

@implementation MyViewController

- (void)loadView
{
    myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
    myTableView.delegate = self;
    self.view = myTableView;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"Selected section:%i row:%i", indexPath.section, indexPath.row);
}

@end

Aquí proporcioné una implementación para el método delegado tableView:didSelectRowAtIndexPath: myTableView llamará cuando sea apropiado (el usuario selecciona una fila).

Aquí puede encontrar todos los métodos de delegado definidos en UITableViewDelegate. Algunos son obligatorios y otros son opcionales:

http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UITableViewDelegate_Protocol/Reference/Reference.html

Para ser un delegado de una clase, debe saber para qué métodos debe proporcionar implementaciones.

Si quisiera crear sus propias definiciones de delegado, crearía un nuevo protocolo. No retiene a sus delegados (consulte la declaración de propiedad), ya que esto crea un ciclo de retención:

// MyViewController.h
@class MyViewController;

@protocol MyViewControllerDelegate
- (void)viewController:(MyViewController *)viewController didChangeSelection:(NSIndexPath *)newIndexPath;
@end

@interface MyViewController : UIViewController <UITableViewDelegate>
@property (nonatomic, retain) UITableView *myTableView;
@property (nonatomic, assign) id<MyViewControllerDelegate> delegate;
@end

Aquí hemos creado un nuevo protocolo. Cualquier clase que quiera responder al mensaje viewController:didChangeSelection: ahora podría hacerlo. Al igual que con la vista de tabla anterior, establecería el delegado en sí mismo y luego implementaría el método. Ahora que tiene un delegado, puede invocar el método en el momento apropiado.

// MyViewController.m
#import "MyViewController.h"

@implementation MyViewController

- (void)loadView
{
    myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
    myTableView.delegate = self;
    self.view = myTableView;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"Selected section:%i row:%i", indexPath.section, indexPath.row);

    indexPath = [NSIndexPath indexPathForRow:1 inSection:0];
    [self.delegate viewController:self didChangeSelection:indexPath];
}

@end

Ahora el delegado puede recibir el mensaje y hacer lo que quiera sabiendo que mi controlador de vista cambió la selección.

contestado el 22 de mayo de 12 a las 22:05

Probablemente debería verificar que el delegado responda a un selector antes de llamarlo, especialmente a los métodos opcionales. - jrtc27

De acuerdo, pero pensé que la respuesta ya se estaba haciendo un poco larga. - sc0rp10n

Excelente explicación. ¡Muchas gracias! - esquizo

Un patrón de delegado es una forma conveniente de permitir la comunicación entre controladores independientes que permiten un acoplamiento débil. Así que digamos que tienes un patrón como este:

        A
       / \
      B   C

Donde A instancia B y C. La comunicación entre A a B y A a C es fácil, pero ¿cómo se comunicaría entre B y C? B a A? C a A? Hay un par de formas diferentes de hacerlo, como la observación de valores clave o las devoluciones de llamadas en bloque. Sin embargo, la delegación todavía se usa con más frecuencia, aunque los bloques se están fortaleciendo.

En este ejemplo, el objeto A instancia el objeto B para crear un objeto y llenarlo con información. ¿Cómo el objeto B le devolvería el nuevo objeto a A si quieres mantener las cosas sueltas? Bueno, con estos 9 sencillos pasos, ¡tú también puedes hacerlo! Puede que no tenga sentido, pero comenzaremos con ClassB...

// ClassB.h

@protocol ClassBDelegate; //(1)

@interface ClassB : NSObject

@property (nonatomic, weak) id<ClassBDelegate>bDelegate; //(2)

-(void)makeNewObjectAndSendBack;

@end

@protocol ClassBDelegate : NSObject //(3)

-(void) classB:(Class B *)theClassB finishedWithObject:(id)finishedObject; //(4)

@end

ClassB.m
@implementation
@synthesize bDelegate = _bDelegate; //(5)

-(void)makeNewObjectAndSendBack {

//something something something
[self.bDelegate classB:self finishedWithObject:newObject]; //(6)

}

@end
  1. definir el protocolo que se establecerá posteriormente
  2. establecer una instancia de un objeto que se ajuste a ese protocolo
  3. establecer el protocolo
  4. configure la llamada al método que usará para enviar el objeto terminado a A.
  5. sintetizar el delegado
  6. después de hacer lo que necesita hacer, lo envía de regreso usando el método que definió en 4

// ClassA.h

@interface ClassA : NSObject <ClassBDelegate> //(7)

@property (nonatomic, strong) ClassB theClassB;

-(void)yourMethodToDoSomething;

@end

ClassA.m
@implementation
@synthesize theClassB = _theClassB; 

-(void)randomMethod {

self.theClassB = [ClassB new];
self.theClassB.bDelegate = self; //(8)
[self.theClassB makeNewObjectAndSendBack];

}

-(void) classB:(Class B *)theClassB finishedWithObject:(id)finishedObject { //(9)
[self doSomethingWithFinishedObject:finishedObject]; //ta-da!
}

@end

7.Cumplir con el protocolo ClassBDelegate. Esto básicamente dice que implementará los métodos definidos en la definición del protocolo.

8.¡Establezca el objeto delegado del objeto classB como uno mismo! Esto es crucial ya menudo se omite.

9.Implemente el método de delegado para cuando recupere el nuevo objeto.

Entonces, el proceso, en resumen, es: A instancia B. A establece el delegado de B como uno mismo. A le dice a B que haga algo. B hace algo y devuelve el objeto a través del método de delegado. A lo recupera.

Para obtener más información, incluido lo que puede hacer con los protocolos, consulte: Big Nerd Ranch habla sobre protocolos Parte 1 Parte 2 Parte 3

¡Buena suerte!

contestado el 22 de mayo de 12 a las 22:05

Excelente explicación. ¡Gracias por tomarse el tiempo para explicar esto a fondo! - esquizo

Parece que puede estar un poco confundido en cuanto a qué son los delegados y cómo se usan. Aquí hay dos enlaces a la documentación de Apple que pueden resultarle útiles: Una visión general conceptual y un más explicacion en profundidad.

contestado el 22 de mayo de 12 a las 21:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.