2011-03-09 23 views
14

He estado luchando con pasar datos entre dos controladores de vista durante un par de días y estoy muy confundido. Soy nuevo en Objective-C y encuentro algunas partes difíciles de entender.Uso de un delegado para pasar datos a la pila de navegación

Tengo un controlador de navegación, FirstView es un formulario y en este formulario tengo un botón que carga SecondView que contiene un TableView para que el usuario seleccione algunas opciones. entonces quiero pasar a la selección de vuelta al controlador FirstView y mostrar los datos, etc ...

He leído mucho sobre esto (stackoverflow, iphonedevsdk, CS 193P Recursos) y las opciones que he visto son,

1) Ivar en delegado de la aplicación (sucio y no se recomienda) 2) crear un producto único 3) crear una clase de modelo de datos 4) Utilizar los protocolos y los delegados (recomendado por manzana)

quiero hacer las cosas bien y quiero usar la opción 4 - Delegados en mi programa

El problema es que no entiendo a los delegados y cómo configurarlos e implementarlos.

¿Alguien podría proporcionar un ejemplo básico sobre cómo configurar y pasar un NSArray utilizando el delegado y 2 controladores de vista.

Gracias de antemano Matt

Respuesta

29

Delegación es el patrón correcto para ser utilizado en este caso, pero su descripción no se parece mucho a la delegación, ya que utiliza una variable global. Quizás esté almacenando variables globales en su delegado de la aplicación que siempre debe tratar de evitar.

He aquí un esbozo de lo que el código debería ser similar:

SecondViewController.h:

@protocol SecondViewControllerDelegate; 

@interface SecondViewController; 

SecondViewController : UIViewController 
{ 
    id<SecondViewControllerDelegate> delegate; 

    NSArray* someArray; 
} 

@property (nonatomic, assign) id<SecondViewControllerDelegate> delegate; 
@property (nonatomic, retain) NSArray* someArray; 

@end 

@protocol SecondViewControllerDelegate 
- (void)secondViewControllerDidFinish:(SecondViewController*)secondViewController; 
@end 

SecondViewController.m:

@implementation SecondViewController 

@synthesize delegate; 
@synthesize someArray; 

- (void)dealloc 
{ 
    [someArray release]; 
    [super dealloc]; 
} 

- (void)someMethodCalledWhenUserIsDone 
{ 
    [delegate secondViewControllerDidFinish:self]; 
} 

FirstViewController.h:

#import SecondViewController 

@interface FirstViewController : UIViewController <SecondViewControllerDelegate> 
{ 
    ... 
} 

@end 

FirstViewController.m:

@implementation FirstViewController 

- (void)secondViewControllerDidFinish:(SecondViewController*)secondViewController 
{ 
    NSArray* someArray = secondViewController.someArray 
    // Do something with the array 
} 

@end 
+2

Muchas gracias por su respuesta, buena referencia para los demás. También hice otra pregunta similar a esto y luego hice un seguimiento con una respuesta completa. http://stackoverflow.com/questions/5210535/passing-data-between-view-controllers –

+0

¿Puede por favor mostrarme cómo hacer lo mismo desde la primera vista hasta la segunda como enviar cadenas de la primera a la segunda vista? Configuración especial para delegar a sí mismo..? gracias de antemano:) – dreamBegin

+0

¿Por qué dar error diciendo "variable de instancia existente" en la creación de ID delegado y la propiedad delegado.? Gracias. – MRizwan33

1

Off parte superior de mi cabeza. Puede reemplazar _returnedProperty con su objeto personalizado y en el método setReturnedProperty hacer toda la magia antes de asignar realmente el valor verificado de la tabla.

@interface FormController : UIViewController { 
    NSString *_returnedProperty; 
} 

@property (nonatomic, retain) NSString *returnedProperty; 

@end 

@implementation FormController 

- (void)showChoices { 
    TableController *tv = [[TableController alloc] initWithDelegate:self]; 
    [self.navigationController pushViewController:tv animated:YES]; 
    [tv release]; 
} 

- (void)setReturnedProperty:(NSString *)string { 
    NSLog(@"Setting property as a delegate"); 
    [_returnedProperty release]; 
    _returnedProperty = [string retain]; 
} 

@synthesize returnedProperty=_returnedProperty; 

@end 

@interface TableController : UITableViewController { 
    id _delegate 
} 
@end 

@implementation TableController 

- (id)initWithDelegate:(id)delegate { 
    self = [super initWithStyle:UITableViewGroupedStyle]; 
    if (!self) return nil; 

    _delegate = delegate; 
    return self; 
} 

- (void)tableView:(UITableView *)tv didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    // do the data retrieval stuff 
    NSString *returnedProperty = @"foo"; 
    [_delegate setReturnedProperty:returnableProperty]; 
} 

@end 
+0

Gracias Elimantas, trató de implementar esto, pero no! ¿Es este verdadero protocolo y delegar la implementación? No veo @protocol y también . ¿Tienes este código en xcode? o simplemente escribiste esto directamente en el cuadro de respuestas? –

+0

No es de xcode. Está directamente en el cuadro de respuesta. Para que este código funcione, no necesita un protocolo (a menos que desee un código limpio sin advertencias de gcc). ¿Qué quiere decir con "falló"? ¿No se llamó el método? Actualizaré el código con setter personalizado. – Eimantas

+0

Obtengo esto: error: specifier-calificador-list esperado antes de 'returnedProperty' para esta línea @property returnedProperty = _returnedProperty; –

0

Usted puede utilizar guión gráfico es bastante fácil. Utilice esta en la implementación de SecondViewController y crear una propiedad en VIewController.h (controlador de la primera vista) llamado dataFromSecondView

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    NSString *textvalue = self.SecondViewText.text; 
    ViewController *destination = segue.destinationViewController; 
    destination.dataFromSecondView = textvalue; 
} 
Cuestiones relacionadas