2011-05-29 7 views
124

Tengo dos UITableViewControllers y necesito pasar el valor del controlador de vista secundaria al padre utilizando un delegado. Sé lo que son los delegados y solo quería ver un ejemplo simple de seguir.¿Cómo configuro un delegado simple para comunicarme entre dos controladores de vista?

Gracias

+1

Si prueba la plantilla Xcode "Utility", ya hay un patrón delegado ya implementado. ¿Necesitas más ayuda que eso quizás? – phi

+0

Aquí hay un tutorial muy simple. http://www.tutorialspoint.com/ios/ios_delegates.htm –

Respuesta

295

ejemplo simple ...

Digamos que el controlador de vista niño tiene una UISlider y queremos pasar el valor del control deslizante de nuevo a la matriz a través de un delegado.

En el archivo de cabecera del controlador de vista del niño, declaran el tipo de delegado y sus métodos:

ChildViewController.h

#import <UIKit/UIKit.h> 

// 1. Forward declaration of ChildViewControllerDelegate - this just declares 
// that a ChildViewControllerDelegate type exists so that we can use it 
// later. 
@protocol ChildViewControllerDelegate; 

// 2. Declaration of the view controller class, as usual 
@interface ChildViewController : UIViewController 

// Delegate properties should always be weak references 
// See http://stackoverflow.com/a/4796131/263871 for the rationale 
// (Tip: If you're not using ARC, use `assign` instead of `weak`) 
@property (nonatomic, weak) id<ChildViewControllerDelegate> delegate; 

// A simple IBAction method that I'll associate with a close button in 
// the UI. We'll call the delegate's childViewController:didChooseValue: 
// method inside this handler. 
- (IBAction)handleCloseButton:(id)sender; 

@end 

// 3. Definition of the delegate's interface 
@protocol ChildViewControllerDelegate <NSObject> 

- (void)childViewController:(ChildViewController*)viewController 
      didChooseValue:(CGFloat)value; 

@end 

En la implementación del controlador de vista del niño, llamar a los métodos de delegado como sea necesario.

ChildViewController.m

#import "ChildViewController.h" 

@implementation ChildViewController 

- (void)handleCloseButton:(id)sender { 
    // Xcode will complain if we access a weak property more than 
    // once here, since it could in theory be nilled between accesses 
    // leading to unpredictable results. So we'll start by taking 
    // a local, strong reference to the delegate. 
    id<ChildViewControllerDelegate> strongDelegate = self.delegate; 

    // Our delegate method is optional, so we should 
    // check that the delegate implements it 
    if ([strongDelegate respondsToSelector:@selector(childViewController:didChooseValue:)]) { 
     [strongDelegate childViewController:self didChooseValue:self.slider.value]; 
    } 
} 

@end 

En el archivo de cabecera del controlador de vista de los padres, declarar que implementa el protocolo ChildViewControllerDelegate.

RootViewController.h

#import <UIKit/UIKit.h> 
#import "ChildViewController.h" 

@interface RootViewController : UITableViewController <ChildViewControllerDelegate> 

@end 

En la implementación del controlador de vista de los padres, poner en práctica los métodos de delegado adecuadamente.

RootViewController.m

#import "RootViewController.h" 

@implementation RootViewController 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    ChildViewController *detailViewController = [[ChildViewController alloc] init]; 
    // Assign self as the delegate for the child view controller 
    detailViewController.delegate = self; 
    [self.navigationController pushViewController:detailViewController animated:YES]; 
} 

// Implement the delegate methods for ChildViewControllerDelegate 
- (void)childViewController:(ChildViewController *)viewController didChooseValue:(CGFloat)value { 

    // Do something with value... 

    // ...then dismiss the child view controller 
    [self.navigationController popViewControllerAnimated:YES]; 
} 

@end 

Espero que esto ayude!

+1

¿Cómo se registra el padre como el delegado del niño? – Madbreaks

+2

Llamando 'detailViewController.delegate = self;' (está en '-tableView: didSelectRowAtIndexPath:' en el fragmento de código anterior. –

+0

Gracias. Si el ChildViewController está delegado en UITableView, ¿dónde deberían estar los métodos UITableView? En el niño o en el padre? – Dejell

30

Este código a continuación solo muestra el uso básico del concepto de delegado ... nombre la variable y la clase según sus necesidades.

En primer lugar tiene que declarar un protocolo:

Digamos que es MyFirstControllerDelegate.h

@protocol MyFirstControllerDelegate 
- (void) FunctionOne: (MyDataOne*) dataOne; 
- (void) FunctionTwo: (MyDatatwo*) dataTwo; 
@end 

importación MyFirstControllerDelegate.h archivo y confirmar su FirstController con el protocolo MyFirstControllerDelegate

#import "MyFirstControllerDelegate.h" 

@interface FirstController : UIViewController<MyFirstControllerDelegate> 
{ 

} 

@end 

En el archivo de implementación, es necesario realizar ambas funciones de protocolo:

@implementation FirstController 


    - (void) FunctionOne: (MyDataOne*) dataOne 
     { 
      //Put your finction code here 
     } 
    - (void) FunctionTwo: (MyDatatwo*) dataTwo 
     { 
      //Put your finction code here 
     } 

    //Call below function from your code 
    -(void) CreateSecondController 
    { 
      SecondController *mySecondController = [SecondController alloc] initWithSomeData:.]; 
      //..... push second controller into navigation stack 
      mySecondController.delegate = self ; 
      [mySecondController release]; 
    } 

@end 

en su SecondController:

@interface SecondController:<UIViewController> 
{ 
    id <MyFirstControllerDelegate> delegate; 
} 

@property (nonatomic,assign) id <MyFirstControllerDelegate> delegate; 

@end 

En el archivo de implementación SecondController.

@implementation SecondController 

@synthesize delegate; 
//Call below two function on self. 
-(void) SendOneDataToFirstController 
{ 
    [delegate FunctionOne:myDataOne]; 
} 
-(void) SendSecondDataToFirstController 
{ 
    [delegate FunctionTwo:myDataSecond]; 
} 

@end 

Here es el artículo de wiki sobre el delegado.

+0

Si bien esto cubre cómo configurar un protocolo delegado en funcionamiento. Creo que es omitir algunos puntos clave. En primer lugar, cuando llame a los métodos en el delegado, primero debe verificar que el delegado responda a ese selector. Si no, tu aplicación se bloqueará.En segundo lugar, debe configurar el "@protocol MyFirstControllerDelegate" en @protocol MyFirstControllerDelegate CW0007007

0

La siguiente solución es un enfoque muy básico y simple para enviar datos de VC2 a VC1 utilizando un delegado.

PS: Esta solución se hace en 9.X Xcode y Swift 4

Declarado un protocolo y creó un delegado var en ViewControllerB

import UIKit 

    //Declare the Protocol into your SecondVC 
    protocol DataDelegate { 
     func sendData(data : String) 
    } 

    class ViewControllerB : UIViewController { 

    //Declare the delegate property in your SecondVC 
     var delegate : DataDelegate? 
     var data : String = "Send data to ViewControllerA." 
     override func viewDidLoad() { 
      super.viewDidLoad() 
     } 

     @IBAction func btnSendDataPushed(_ sender: UIButton) { 
       // Call the delegate method from SecondVC 
       self.delegate?.sendData(data:self.data) 
       dismiss(animated: true, completion: nil) 
      } 
     } 

ViewControllerA confirma la protocolo y espera recibir datos a través del método de delegado sendData

import UIKit 
     // Conform the DataDelegate protocol in ViewControllerA 
     class ViewControllerA : UIViewController , DataDelegate { 
     @IBOutlet weak var dataLabel: UILabel! 

     override func viewDidLoad() { 
      super.viewDidLoad() 
     } 

     @IBAction func presentToChild(_ sender: UIButton) { 
      let childVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier:"ViewControllerB") as! ViewControllerB 
      //Registered delegate 
      childVC.delegate = self 
      self.present(childVC, animated: true, completion: nil) 
     } 

     // Implement the delegate method in ViewControllerA 
     func sendData(data : String) { 
      if data != "" { 
       self.dataLabel.text = data 
      } 
     } 
    } 
Cuestiones relacionadas