Как настроить простой делегат для связи между двумя контроллерами представлений?

У меня есть два UITableViewControllers и нужно передать значение из контроллера дочернего представления родительскому элементу с помощью делегата. Я знаю, что есть делегаты и просто хотел увидеть простой пример.

Спасибо

Ответ 1

Простой пример...

Предположим, что контроллер дочернего представления имеет UISlider, и мы хотим передать значение ползунка обратно родительскому элементу через делегат.

В файле заголовка контроллера дочернего представления объявите тип делегата и его методы:

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 childViewController:didChooseValue: 
// method inside this handler.
- (IBAction)handleCloseButton:(id)sender;

@end

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

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

@end

В реализации контроллера дочернего представления вызовите методы делегата по мере необходимости.

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

В заголовочном файле контроллера родительского представления объявите, что он реализует протокол ChildViewControllerDelegate.

RootViewController.h

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

@interface RootViewController : UITableViewController <ChildViewControllerDelegate>

@end

В реализации контроллера родительского представления выполните соответствующие методы делегата.

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

Надеюсь, это поможет!

Ответ 2

В этом нижеприведенном коде просто показано, как использовать концепцию делегата очень просто. Вы называете переменную и класс согласно вашему требованию.

Сначала вам нужно объявить протокол:

Назовите его MyFirstControllerDelegate.h

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

Импортируйте файл MyFirstControllerDelegate.h и подтвердите свой FirstController с протоколом MyFirstControllerDelegate

#import "MyFirstControllerDelegate.h"

@interface FirstController : UIViewController<MyFirstControllerDelegate>
{

}

@end

В файле реализации вам необходимо реализовать обе функции протокола:

@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

в SecondController:

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

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

@end

В файле реализации SecondController.

@implementation SecondController

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

@end

Здесь - статья wiki для делегата.