İki görünüm denetleyicisi arasında iletişim kurmak için nasıl basit bir temsilci ayarlayabilirim?


136

Ben iki tane var UITableViewControllersve bir temsilci kullanarak değeri çocuk görünümü denetleyicisinden ebeveyn için geçmesi gerekiyor. Delegelerin ne olduğunu biliyorum ve sadece basit bir örnek görmek istedim.

Teşekkür ederim


1
"Yardımcı Program" Xcode şablonunu denerseniz, zaten uygulanmış bir temsilci kalıbı vardır. Bundan daha fazla yardıma mı ihtiyacınız var?
phi

İşte çok basit bir öğretici. tutorialspoint.com/ios/ios_delegates.htm
Muhammad_Awaab

Yanıtlar:


304

Basit bir örnek ...

Diyelim ki alt görünüm denetleyicisinde bir UISliderve bir kaydırıcı değerini bir temsilci aracılığıyla üst öğeye geri geçirmek istiyoruz.

Alt görünüm denetleyicisinin başlık dosyasında, temsilci türünü ve yöntemlerini bildirin:

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

Alt görünüm denetleyicisinin uygulamasında, temsilci yöntemlerini gerektiği gibi çağırın.

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

Üst görünüm denetleyicisinin başlık dosyasında, ChildViewControllerDelegateprotokolü uyguladığını bildirin.

RootViewController.h

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

@interface RootViewController : UITableViewController <ChildViewControllerDelegate>

@end

Üst görünüm denetleyicisinin uygulamasında, temsilci yöntemlerini uygun şekilde uygulayın.

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

Bu yardımcı olur umarım!


1
Ebeveyn, çocuğun delegesi olarak nasıl kaydolur?
Madbreaks

2
Arayarak detailViewController.delegate = self;( -tableView:didSelectRowAtIndexPath:yukarıdaki kod snippet'inde.
Simon Whitaker

Teşekkürler. ChildViewController UITableView için temsilci ise, UITableView yöntemleri nerede olmalıdır? Çocukta mı yoksa ebeveynte mi?
Dejell

Harika bir örnek / açıklama! Ne yazık ki, derlemeye çalıştığımda "MyProtocol 'için protokol bildirimi bulunamıyor" hatası alıyorum. Bununla birlikte, açıkladığınız gibi: ortaya çıkan viewcontroller .h dosyasında procotol tanımına sahiptir ve .m dosyasında protokol yöntemini çağırır. Barındırma viewcontroller .h @interface bildiriminde <MyProtocol> vardır - bu da hatanın gerçekleştiği yerdir. Cevabınız aynı gözüküyor, yine de ... herhangi bir fikir?
Danny

Teşekkür ederim. En az bir düzine kaynağa baktım ve bunu takip edebildiğim ilk kaynak. Numaralı kod yorumlarının sırasını açıklamak için harika çalıştığını düşünüyorum.
JaseC

32

Aşağıdaki kod sadece temsilci kavramının çok temel kullanımını göstermektedir .. değişken ve sınıf gereksiniminize göre adlandırın.

İlk önce bir protokol beyan etmeniz gerekir:

Buna MyFirstControllerDelegate.h diyelim

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

MyFirstControllerDelegate.h dosyasını içe aktarın ve FirstController'ınızı MyFirstControllerDelegate protokolüyle onaylayın

#import "MyFirstControllerDelegate.h"

@interface FirstController : UIViewController<MyFirstControllerDelegate>
{

}

@end

Uygulama dosyasında, protokolün her iki işlevini de uygulamanız gerekir:

@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

sizin de SecondController :

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

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

@end

Uygulama dosyasında SecondController .

@implementation SecondController

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

@end

Buraya delege hakkındaki wiki makalesi.


Bu, çalışan bir Delege protokolünün nasıl kurulacağını kapsar. Sanırım birkaç önemli noktayı gözden kaçırıyor. Öncelikle, temsilci üzerindeki yöntemleri çağırırken, önce temsilcinin bu seçiciye yanıt verip vermediğini kontrol etmelisiniz. Bunu yapmazsanız uygulamanız kilitlenir. İkinci olarak, "@protocol MyFirstControllerDelegate" i @protocol MyFirstControllerDelegate <NSObject> olarak ayarlamanız gerekir
CW0007007

6

Aşağıdaki çözüm, temsilci kullanarak VC2'den VC1'e veri göndermek için çok temel ve basit bir yaklaşımdır.

Not: Bu çözüm Xcode 9.X ve Swift 4'te yapılmıştır

Bir protokol bildirildi ve ViewControllerB içine bir delege var oluşturdu

    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 protokolü onaylar ve sendData delege yöntemi ile veri alması beklenir

    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
            }
        }
    }

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.