두 개의 뷰 컨트롤러간에 통신하기 위해 간단한 델리게이트를 어떻게 설정합니까?


136

두 가지가 UITableViewControllers있으며 델리게이트를 사용하여 자식 뷰 컨트롤러에서 부모로 값을 전달해야합니다. 나는 대의원이 무엇인지 알고 있으며 따라하기 간단한 예를보고 싶었습니다.

감사합니다


1
"유틸리티"Xcode 템플릿을 사용하려고하면 이미 구현 된 대리자 패턴이 있습니다. 그보다 더 많은 도움이 필요하십니까?
phi

다음은 매우 간단한 자습서입니다. tutorialspoint.com/ios/ios_delegates.htm
Muhammad_Awaab

답변:


304

간단한 예 ...

자식 뷰 컨트롤러에 a가 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'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

자식 뷰 컨트롤러의 구현에서 필요에 따라 대리자 메서드를 호출하십시오.

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

도움이 되었기를 바랍니다!


1
부모는 어떻게 자녀의 대리인으로 등록합니까?
Madbreaks

2
전화로 detailViewController.delegate = self;( -tableView:didSelectRowAtIndexPath:위의 코드 스 니펫에 있습니다.
Simon Whitaker

감사. ChildViewController가 UITableView에 위임 된 경우 UITableView 메소드는 어디에 있어야합니까? 아이 또는 부모?
Dejell

훌륭한 예 / 설명! 불행히도, 컴파일하려고 할 때 " 'MyProtocol'에 대한 프로토콜 선언을 찾을 수 없습니다"오류가 발생합니다. 그러나 생성 된 뷰 컨트롤러는 .h 파일에 프로 코톨 정의를 가지며 .m 파일에서 프로토콜 메소드를 호출합니다. 호스팅 뷰 컨트롤러에는 .h @interface 선언에 <MyProtocol>이 있습니다.이 오류가 발생합니다. 그래도 당신의 대답은 같은 것 같습니다 ... 어떤 아이디어?
Danny

감사합니다. 나는 최소한 12 개의 자원을 보았고 이것이 내가 따라온 첫 번째 자료입니다. 번호가 매겨진 코드 주석은 그 순서를 설명하는 데 도움이된다고 생각합니다.
JaseC

32

아래 코드는 델리게이트 개념의 매우 기본적인 사용법을 보여줍니다. 요구 사항에 따라 변수 및 클래스 이름을 지정합니다.

먼저 프로토콜을 선언해야합니다.

그것을 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

다음 은 델리게이트에 관한 위키 기사입니다.


여기에는 작동하는 델리게이트 프로토콜을 설정하는 방법이 포함됩니다. 몇 가지 핵심 사항을 생략하고 있다고 생각합니다. 먼저 델리게이트에서 메소드를 호출 할 때 먼저 델리게이트가 해당 선택기에 응답하는지 확인해야합니다. 그렇지 않으면 앱이 다운됩니다. 둘째 당신은 "@protocol MyFirstControllerDelegate"에 @protocol MyFirstControllerDelegate <NSObject의> 설정해야합니다
CW0007007

6

다음 솔루션은 delegate를 사용하여 VC2에서 VC1로 데이터를 전송하는 매우 기본적이고 간단한 방법입니다.

PS :이 솔루션은 Xcode 9.X 및 Swift 4 에서 만들어졌습니다.

프로토콜 선언 및 ViewControllerB에 델리게이트 var 생성

    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 는 프로토콜을 확인하고 델리게이트 메소드 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
            }
        }
    }

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.