Bagaimana cara menyiapkan delegasi sederhana untuk berkomunikasi antara dua pengontrol tampilan?

136

Saya memiliki dua UITableViewControllersdan harus meneruskan nilai dari pengontrol tampilan anak ke orang tua menggunakan delegasi. Saya tahu apa itu delegasi dan hanya ingin melihat contoh sederhana untuk diikuti.

Terima kasih

jini
sumber
1
Jika Anda mencoba template Xcode "Utilitas", ada pola delegasi yang sudah diterapkan. Apakah Anda membutuhkan bantuan lebih dari itu?
phi
Berikut ini tutorial yang sangat sederhana. tutorialspoint.com/ios/ios_delegates.htm
Muhammad_Awaab

Jawaban:

304

Contoh sederhana ...

Misalkan pengontrol tampilan anak memiliki a UISliderdan kami ingin meneruskan nilai slider kembali ke induk melalui delegasi.

Di file header pengontrol tampilan anak, nyatakan jenis delegasi dan metodenya:

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

Dalam implementasi pengontrol tampilan anak, panggil metode delegasi sesuai kebutuhan.

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

Dalam file header pengontrol tampilan induk, nyatakan bahwa itu mengimplementasikan ChildViewControllerDelegateprotokol.

RootViewController.h

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

@interface RootViewController : UITableViewController <ChildViewControllerDelegate>

@end

Dalam implementasi pengontrol tampilan induk, implementasikan metode delegasi dengan tepat.

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

Semoga ini membantu!

Simon Whitaker
sumber
1
Bagaimana orang tua mendaftar sebagai delegasi anak?
Madbreaks
2
Dengan menelepon detailViewController.delegate = self;(ada dalam -tableView:didSelectRowAtIndexPath:potongan kode di atas.
Simon Whitaker
Terima kasih. Jika ChildViewController didelegasikan ke UITableView, di mana seharusnya metode UITableView berada? Pada anak atau orang tua?
Dejell
Contoh / penjelasan yang bagus! Sayangnya, saya mendapatkan pesan kesalahan "Tidak dapat menemukan deklarasi protokol untuk 'MyProtocol'" saat mencoba mengompilasi. Seperti yang Anda jelaskan: viewcontroller yang muncul memiliki definisi procotol dalam file .h-nya dan memanggil metode protokol dalam file .m-nya. Viewcontroller hosting memiliki <MyProtocol> dalam deklarasi .h @interface - tempat kesalahan terjadi. Jawaban Anda sepertinya sama, meskipun ... ada ide?
Danny
Terima kasih. Saya telah melihat setidaknya selusin sumber daya dan ini adalah sumber pertama yang dapat saya ikuti. Saya pikir komentar kode bernomor bekerja sangat baik untuk membantu menjelaskan urutannya.
JaseC
32

Kode di bawah ini hanya menunjukkan penggunaan yang paling dasar dari konsep delegasi .. Anda memberi nama variabel dan kelas sesuai kebutuhan Anda.

Pertama, Anda perlu mendeklarasikan protokol:

Sebut saja MyFirstControllerDelegate.h

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

Impor file MyFirstControllerDelegate.h dan konfirmasi FirstController Anda dengan protokol MyFirstControllerDelegate

#import "MyFirstControllerDelegate.h"

@interface FirstController : UIViewController<MyFirstControllerDelegate>
{

}

@end

Dalam file implementasi, Anda perlu mengimplementasikan kedua fungsi protokol:

@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

di SecondController Anda :

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

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

@end

Dalam file implementasi SecondController .

@implementation SecondController

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

@end

Berikut adalah artikel wiki tentang delegasi.

Jhaliya
sumber
Sementara ini mencakup cara menyiapkan protokol Delegasi yang berfungsi. Saya pikir ini menghilangkan beberapa poin penting. Pertama, saat memanggil metode pada delegasi, Anda harus terlebih dahulu memeriksa apakah delegasi merespons selektor itu. Jika tidak, aplikasi Anda akan macet. Kedua, Anda perlu menyetel "@protocol MyFirstControllerDelegate" ke @protocol MyFirstControllerDelegate <NSObject>
CW0007007
6

Solusi berikut adalah pendekatan yang sangat mendasar dan sederhana untuk mengirim data dari VC2 ke VC1 menggunakan delegasi.

PS: Solusi ini dibuat di Xcode 9.X dan Swift 4

Mendeklarasikan protokol dan membuat var delegasi ke 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 mengonfirmasi protokol dan diharapkan menerima data melalui metode delegasi 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
            }
        }
    }
Tim iOS
sumber