문제

나는 대리인이 어떻게 작동하는지 알고 있으며 어떻게 사용할 수 있는지 알고 있습니다.

하지만 어떻게 생성하나요?

도움이 되었습니까?

해결책

목표 C의 대표는 delegate 다른 대상. 하나를 만들려면 관심있는 대의원 방법을 구현하는 클래스를 정의하고 해당 클래스를 대의원 프로토콜을 구현하는 것으로 표시하십시오.

예를 들어, 당신이 있다고 가정합니다 UIWebView. 대의원을 구현하고 싶다면 webViewDidStartLoad: 방법, 다음과 같은 클래스를 만들 수 있습니다.

@interface MyClass<UIWebViewDelegate>
// ...
@end

@implementation MyClass
- (void)webViewDidStartLoad:(UIWebView *)webView { 
    // ... 
}
@end

그런 다음 MyClass 인스턴스를 작성하여 웹보기의 대의원으로 할당 할 수 있습니다.

MyClass *instanceOfMyClass = [[MyClass alloc] init];
myWebView.delegate = instanceOfMyClass;

UIWebView 측면, 대의원이 webViewDidStartLoad: 사용 사용 respondsToSelector: 그리고 적절한 경우 보내십시오.

if([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
    [self.delegate webViewDidStartLoad:self];
}

대의원 자체는 일반적으로 선언됩니다 weak (아크) 또는 assign (사전 ARC) 객체의 대의원은 종종 해당 객체에 대한 강력한 참조를 가지고 있기 때문에 루프를 유지하지 않습니다. (예를 들어,보기 컨트롤러는 종종 포함 된보기의 대의원입니다.)

수업 대의원

자신의 대의원을 정의하려면 프로토콜에 대한 Apple 문서. 일반적으로 공식 프로토콜을 선언합니다. Uiwebview.h에서 논의 된 선언은 다음과 같습니다.

@protocol UIWebViewDelegate <NSObject>
@optional
- (void)webViewDidStartLoad:(UIWebView *)webView;
// ... other methods here
@end

이것은 대의원을위한 특수 유형을 생성하기 때문에 인터페이스 또는 추상 기본 클래스와 유사합니다. UIWebViewDelegate 이 경우. 대의원 도구는이 프로토콜을 채택해야합니다.

@interface MyClass <UIWebViewDelegate>
// ...
@end

그런 다음 프로토콜에서 메소드를 구현하십시오. 프로토콜에서 선언 된 방법 @optional (대부분의 대표 방법과 마찬가지로) -respondsToSelector: 특정 방법을 호출하기 전에.

이름 지정

대의원 메소드는 일반적으로 위임 클래스 이름으로 시작하여 위임 객체를 첫 번째 매개 변수로 취합니다. 그들은 또한 종종 유언장, 또는해야 할 형태를 사용합니다. 그래서, webViewDidStartLoad: (첫 번째 매개 변수는 웹보기) loadStarted (매개 변수를 취하지 않음) 예를 들어.

속도 최적화

메시지를 보내려고 할 때마다 대의원이 선택기에 응답하는지 여부를 확인하는 대신 대의원을 설정할 때 해당 정보를 캐시 할 수 있습니다. 이를 수행하는 매우 깨끗한 방법 중 하나는 다음과 같이 비트 필드를 사용하는 것입니다.

@protocol SomethingDelegate <NSObject>
@optional
- (void)something:(id)something didFinishLoadingItem:(id)item;
- (void)something:(id)something didFailWithError:(NSError *)error;
@end

@interface Something : NSObject
@property (nonatomic, weak) id <SomethingDelegate> delegate;
@end

@implementation Something {
  struct {
    unsigned int didFinishLoadingItem:1;
    unsigned int didFailWithError:1;
  } delegateRespondsTo;
}
@synthesize delegate;

- (void)setDelegate:(id <SomethingDelegate>)aDelegate {
  if (delegate != aDelegate) {
    delegate = aDelegate;

    delegateRespondsTo.didFinishLoadingItem = [delegate respondsToSelector:@selector(something:didFinishLoadingItem:)];
    delegateRespondsTo.didFailWithError = [delegate respondsToSelector:@selector(something:didFailWithError:)];
  }
}
@end

그런 다음 신체에서 우리는 대의원이 우리의 delegateRespondsTo 보내기보다는 구조 -respondsToSelector: 다시 반복하여.

비공식 대표

프로토콜이 존재하기 전에 사용하는 것이 일반적이었습니다. 범주 ~에 NSObject 대의원이 구현할 수있는 방법을 선언합니다. 예를 들어, CALayer 여전히 이것을합니다 :

@interface NSObject(CALayerDelegate)
- (void)displayLayer:(CALayer *)layer;
// ... other methods here
@end

이것은 본질적으로 모든 객체가 구현할 수 있음을 컴파일러에게 알려줍니다. displayLayer:.

그런 다음 동일하게 사용합니다 -respondsToSelector: 이 방법을 호출하기 위해 위에서 설명한대로 접근합니다. 대의원은 단순히이 방법을 구현하고 할당합니다 delegate 속성, 그리고 그것이 바로 그 것입니다 (당신이 프로토콜을 준수하는 것을 선언하지는 않습니다). 이 방법은 Apple의 라이브러리에서 일반적이지만 새로운 코드는 위의보다 현대적인 프로토콜 접근법을 사용해야합니다. NSObject (AutoComplete가 덜 유용하게 만들고 컴파일러가 오타 및 유사한 오류에 대해 경고하기가 어렵습니다.

다른 팁

승인 된 답변은 훌륭하지만 1 분의 답변을 찾고 있다면 다음을 시도하십시오.

myclass.h 파일은 다음과 같아야합니다 (주석이있는 대의원 추가!)

#import <BlaClass/BlaClass.h>

@class MyClass;             //define class, so protocol can see MyClass
@protocol MyClassDelegate <NSObject>   //define delegate protocol
    - (void) myClassDelegateMethod: (MyClass *) sender;  //define delegate method to be implemented within another class
@end //end protocol

@interface MyClass : NSObject {
}
@property (nonatomic, weak) id <MyClassDelegate> delegate; //define MyClassDelegate as delegate

@end

myclass.m 파일은 다음과 같아야합니다

#import "MyClass.h"
@implementation MyClass 
@synthesize delegate; //synthesise  MyClassDelegate delegate

- (void) myMethodToDoStuff {
    [self.delegate myClassDelegateMethod:self]; //this will call the method implemented in your other class    
}

@end

다른 클래스에서 대의원을 사용하려면 (이 경우 MyVC라고 불리는 UIViewController) MyVC.H :

#import "MyClass.h"
@interface MyVC:UIViewController <MyClassDelegate> { //make it a delegate for MyClassDelegate
}

myvc.m :

myClass.delegate = self;          //set its delegate to self somewhere

대의원 방법을 구현하십시오

- (void) myClassDelegateMethod: (MyClass *) sender {
    NSLog(@"Delegates are great!");
}

대의원 지원을 만들기 위해 공식 프로토콜 방법을 사용할 때 다음과 같은 것을 추가하여 적절한 유형 확인 (런타임이 아닌 컴파일 시간)을 확인할 수 있음을 발견했습니다.

if (![delegate conformsToProtocol:@protocol(MyDelegate)]) {
    [NSException raise:@"MyDelegate Exception"
                format:@"Parameter does not conform to MyDelegate protocol at line %d", (int)__LINE__];
}

Delegate Accessor (SetDelegate) 코드에서. 이것은 실수를 최소화하는 데 도움이됩니다.

어쩌면 이것은 당신이 놓친 것의 선을 더 많이 따라 다닐 것입니다.

C ++ 유사한 관점에서오고 있다면 대표는 약간 익숙해 지지만 기본적으로 '단지 작동합니다'.

그것이 작동하는 방식은 NSWINDOW의 대의원으로 쓴 객체를 설정하지만, 객체에는 가능한 많은 대의원 방법 중 하나 또는 몇 가지에 대한 구현 (메소드) 만 있습니다. 그래서 뭔가 일어나고 NSWindow 당신의 객체를 호출하고 싶어 - 그것은 단지 Objective -C를 사용합니다. respondsToSelector 객체가 해당 메소드가 호출되는지 여부를 결정한 다음 호출하는 방법. 이것이 객관적인 C의 작동 방식입니다.

자신의 대상으로 이것을하는 것은 완전히 사소한 일입니다. 특별한 일이 없습니다. 예를 들어 NSArray 27 개 객체, 모든 다른 종류의 물체 중 18 개만이 방법을 가지고 있습니다. -(void)setToBue; 다른 9 명은 그렇지 않습니다. 그래서 전화합니다 setToBlue 18 개 모두에서 다음과 같은 작업을 수행해야합니다.

for (id anObject in myArray)
{
  if ([anObject respondsToSelector:@selector(@"setToBlue")])
     [anObject setToBlue]; 
}

대의원에 대한 또 다른 점은 그들이 유지되지 않았다는 것입니다. 그래서 당신은 항상 대의원을 설정해야합니다. nil 당신의 MyClass dealloc 방법.

제발! 아래 간단한 단계별 튜토리얼을 확인하여 대의원이 iOS에서 어떻게 작동하는지 이해하십시오.

iOS의 대표

두 개의 ViewControllers를 만들었습니다 (데이터를 서로 보내기 위해)

  1. FirstViewController DELEGATE (데이터 제공)를 구현합니다.
  2. SecondViewController 대의원을 선언합니다 (데이터를 수신합니다).

Apple이 권장하는 모범 사례로서, 대의원 (정의에 따라 프로토콜)에 적합합니다. NSObject 규약.

@protocol MyDelegate <NSObject>
    ...
@end

& 대의원 내에서 옵션 메소드를 만들려면 (즉, 반드시 구현할 필요가없는 방법)를 사용할 수 있습니다. @optional 이와 같은 주석 :

@protocol MyDelegate <NSObject>
    ...
    ...
      // Declaration for Methods that 'must' be implemented'
    ...
    ...
    @optional
    ...
      // Declaration for Methods that 'need not necessarily' be implemented by the class conforming to your delegate
    ...
@end

따라서 선택 사항으로 지정된 메소드를 사용하는 경우 (수업에서) 확인해야합니다. respondsToSelector (대의원을 준수하는 뷰)가 실제로 선택 방법을 구현 한 경우.

대표자를 이해하면 이러한 모든 답변이 많은 의미가 있다고 생각합니다.개인적으로 저는 C/C++의 세계에서 왔고 Fortran 등과 같은 절차적 언어 이전에 왔으므로 여기에 C++ 패러다임에서 유사한 유사어를 찾는 데 2분 정도 소요됩니다.

C++/Java 프로그래머에게 위임을 설명한다면 다음과 같이 말할 것입니다.

대리인이란 무엇입니까?이는 다른 클래스 내의 클래스에 대한 정적 포인터입니다.포인터를 할당하면 해당 클래스의 함수/메서드를 호출할 수 있습니다.따라서 클래스의 일부 기능은 다른 클래스에 "위임"됩니다(C++ 세계에서는 클래스 개체 포인터가 가리키는 포인터).

프로토콜이란 무엇입니까?개념적으로 이는 위임 클래스로 할당하는 클래스의 헤더 파일과 유사한 목적으로 사용됩니다.프로토콜은 포인터가 클래스 내에서 대리자로 설정된 클래스에서 구현되어야 하는 메서드를 정의하는 명시적인 방법입니다.

C++에서 비슷한 작업을 어떻게 수행할 수 있나요?C++에서 이 작업을 수행하려면 클래스 정의에서 클래스(객체)에 대한 포인터를 정의한 다음 이를 기본 클래스에 대한 대리자로 추가 기능을 제공할 다른 클래스에 연결하면 됩니다.그러나 이 연결은 코드 내에서 유지되어야 하며 서투르고 오류가 발생하기 쉽습니다.Objective C는 프로그래머가 이 규정을 가장 잘 유지하지 못한다고 가정하고 깔끔한 구현을 시행하기 위해 컴파일러 제한 사항을 제공합니다.

스위프트 버전

대의원은 다른 수업을 위해 일하는 수업 일뿐입니다. Swift에서 어떻게 이루어 지는지를 보여주는 다소 어리석은 (그러나 희망적으로 깨달음) 놀이터 예제에 대한 다음 코드를 읽으십시오.

// A protocol is just a list of methods (and/or properties) that must
// be used by any class that adopts the protocol.
protocol OlderSiblingDelegate: class {
    // This protocol only defines one required method
    func getYourNiceOlderSiblingAGlassOfWater() -> String
}

class BossyBigBrother {

    // The delegate is the BossyBigBrother's slave. This position can 
    // be assigned later to whoever is available (and conforms to the 
    // protocol).
    weak var delegate: OlderSiblingDelegate?

    func tellSomebodyToGetMeSomeWater() -> String? {
        // The delegate is optional because there might not be anyone
        // nearby to boss around.
        return delegate?.getYourNiceOlderSiblingAGlassOfWater()
    }
}

// PoorLittleSister conforms to the OlderSiblingDelegate protocol
class PoorLittleSister: OlderSiblingDelegate {

    // This method is repquired by the protocol, but the protocol said
    // nothing about how it needs to be implemented.
    func getYourNiceOlderSiblingAGlassOfWater() -> String {
        return "Go get it yourself!"
    }

}

// initialize the classes
let bigBro = BossyBigBrother()
let lilSis = PoorLittleSister()

// Set the delegate 
// bigBro could boss around anyone who conforms to the 
// OlderSiblingDelegate protocol, but since lilSis is here, 
// she is the unlucky choice.
bigBro.delegate = lilSis

// Because the delegate is set, there is a class to do bigBro's work for him.
// bigBro tells lilSis to get him some water.
if let replyFromLilSis = bigBro.tellSomebodyToGetMeSomeWater() {
    print(replyFromLilSis) // "Go get it yourself!"
}

실제로, 대의원은 종종 다음 상황에서 사용됩니다.

  1. 수업이 일부 정보를 다른 클래스에 전달 해야하는 경우
  2. 클래스가 다른 클래스를 사용자 정의하도록 허용하는 경우

대의원 클래스가 필요한 프로토콜을 준수한다는 점을 제외하고는 수업은 미리 서로에 대해 아무것도 알 필요가 없습니다.

다음 두 기사를 읽는 것이 좋습니다. 그들은 내가 대표들보다 더 잘 이해하는 데 도움이되었습니다 선적 서류 비치 했다.

좋아, 이것은 실제로 질문에 대한 답이 아니지만, 자신의 대의원을 만드는 방법을 찾고 있다면 훨씬 간단한 것이 더 나은 대답이 될 수 있습니다.

거의 필요하지 않기 때문에 대의원을 거의 구현하지 않습니다. 대의원에 대한 대의원 단 한 명만 가질 수 있습니다. 따라서 한 가지 방식으로 의사 소통/전달 데이터에 대한 대의원을 원한다면 알림보다 훨씬 나은 것보다 더 좋습니다.

NSNotification은 물체를 한 명 이상의 수신자에게 전달할 수 있으며 사용하기가 매우 쉽습니다. 다음과 같이 작동합니다.

myclass.m 파일은 다음과 같아야합니다

#import "MyClass.h"
@implementation MyClass 

- (void) myMethodToDoStuff {
//this will post a notification with myClassData (NSArray in this case)  in its userInfo dict and self as an object
[[NSNotificationCenter defaultCenter] postNotificationName:@"myClassUpdatedData"
                                                    object:self
                                                  userInfo:[NSDictionary dictionaryWithObject:selectedLocation[@"myClassData"] forKey:@"myClassData"]];
}
@end

다른 클래스에서 알림을 사용하려면 : 관찰자로 클래스를 추가하십시오.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(otherClassUpdatedItsData:) name:@"myClassUpdatedData" object:nil];

선택기 구현 :

- (void) otherClassUpdatedItsData:(NSNotification *)note {
    NSLog(@"*** Other class updated its data ***");
    MyClass *otherClass = [note object];  //the object itself, you can call back any selector if you want
    NSArray *otherClassData = [note userInfo][@"myClassData"]; //get myClass data object and do whatever you want with it
}

수업을 관찰자로 제거하는 것을 잊지 마십시오.

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

당신이 개발 한 수업이 있고 일부 이벤트가 발생할 때 알릴 수 있도록 대의원 자산을 선언하고 싶다고 가정 해 봅시다.

@class myClass;

@protocol myClassDelegate <NSObject>

-(void)myClass:(MyClass*)myObject requiredEventHandlerWithParameter:(ParamType*)param;

@optional
-(void)myClass:(MyClass*)myObject optionalEventHandlerWithParameter:(ParamType*)param;

@end


@interface MyClass : NSObject

@property(nonatomic,weak)id< MyClassDelegate> delegate;

@end

그래서 당신은 프로토콜을 선언합니다 MyClass 헤더 파일 (또는 별도의 헤더 파일) 및 대의원이 구현 해야하는 필수/선택적 이벤트 핸들러를 선언 한 다음 속성을 선언합니다. MyClass 유형 (id< MyClassDelegate>) 이는 프로토콜을 준수하는 목표 C 클래스를 의미합니다. MyClassDelegate , 당신은 대의원 재산이 약한 것으로 선언된다는 것을 알 수 있습니다. 이것은 보유주기를 방지하는 데 매우 중요합니다 (대부분 대의원은 MyClass 인스턴스 따라서 대의원을 보유라고 선언하면 두 사람 모두 서로를 유지하고 어느 쪽도 공개되지 않을 것입니다).

또한 프로토콜 메소드가 MyClass 매개 변수로 대의원에 대한 인스턴스, 이것은 대의원이 일부 메소드를 호출하려는 경우 모범 사례입니다. MyClass 인스턴스 및 대의원이 스스로를 MyClassDelegate 다중 MyClass 여러 가지가있을 때와 같은 인스턴스 UITableView's 당신의 인스턴스 ViewController 그리고 스스로를 선언합니다 UITableViewDelegate 그들 모두에게.

그리고 당신의 내부 MyClass 다음과 같이 선언 된 이벤트를 대표에게 알립니다.

if([_delegate respondsToSelector:@selector(myClass: requiredEventHandlerWithParameter:)])
{
     [_delegate myClass:self requiredEventHandlerWithParameter:(ParamType*)param];
}

먼저 대의원이 Delegate가 구현하지 않고 앱이 충돌하여 (프로토콜 메소드가 필요한 경우에도) 대의원이 호출하려는 프로토콜 메소드에 응답하는지 확인합니다.

다음은 대의원을 만드는 간단한 방법입니다

.h 파일에서 프로토콜을 만듭니다. @class를 사용하여 프로토콜에 정의 된 다음 UIViewController의 이름을 정의하십시오. < As the protocol I am going to use is UIViewController class>.

1 단계 : UIViewController 클래스의 서브 클래스가 될 "YourViewController"라는 새 클래스 프로토콜을 작성 하고이 클래스를 두 번째 ViewController에 할당하십시오.

2 단계 : "YourViewController"파일로 이동하여 다음과 같이 수정하십시오.

#import <UIKit/UIkit.h>
@class YourViewController;

@protocol YourViewController Delegate <NSObject>

 @optional
-(void)defineDelegateMethodName: (YourViewController *) controller;

@required
-(BOOL)delegateMethodReturningBool: (YourViewController *) controller;

  @end
  @interface YourViewController : UIViewController

  //Since the property for the protocol could be of any class, then it will be marked as a type of id.

  @property (nonatomic, weak) id< YourViewController Delegate> delegate;

@end

프로토콜 동작에 정의 된 방법은 프로토콜 정의의 일부로 @optional으로 제어되고 @required 될 수 있습니다.

단계 : 3 : 대표의 구현

    #import "delegate.h"

   @interface YourDelegateUser ()
     <YourViewControllerDelegate>
   @end

   @implementation YourDelegateUser

   - (void) variousFoo {
      YourViewController *controller = [[YourViewController alloc] init];
      controller.delegate = self;
   }

   -(void)defineDelegateMethodName: (YourViewController *) controller {
      // handle the delegate being called here
   }

   -(BOOL)delegateMethodReturningBool: (YourViewController *) controller {
      // handle the delegate being called here
      return YES;
   }

   @end

// 메소드를 호출하기 전에 정의되었는지 테스트

 - (void) someMethodToCallDelegate {
     if ([[self delegate] respondsToSelector:@selector(defineDelegateMethodName:)]) {
           [self.delegate delegateMethodName:self]; 
     }
  }

자신의 대의원을 만들려면 먼저 구현하지 않고 프로토콜을 만들고 필요한 방법을 선언해야합니다. 그런 다음이 프로토콜을 대의원 또는 대표 방법을 구현하려는 헤더 클래스에 구현하십시오.

프로토콜은 다음과 같이 선언해야합니다.

@protocol ServiceResponceDelegate <NSObject>

- (void) serviceDidFailWithRequestType:(NSString*)error;
- (void) serviceDidFinishedSucessfully:(NSString*)success;

@end

이것은 일부 작업을 수행 해야하는 서비스 클래스입니다. 대의원을 정의하는 방법과 대의원을 설정하는 방법을 보여줍니다. 작업이 완료된 후 구현 클래스에서 대의원의 메소드가 호출됩니다.

@interface ServiceClass : NSObject
{
id <ServiceResponceDelegate> _delegate;
}

- (void) setDelegate:(id)delegate;
- (void) someTask;

@end

@implementation ServiceClass

- (void) setDelegate:(id)delegate
{
_delegate = delegate;
}

- (void) someTask
{
/*

   perform task

*/
if (!success)
{
[_delegate serviceDidFailWithRequestType:@”task failed”];
}
else
{
[_delegate serviceDidFinishedSucessfully:@”task success”];
}
}
@end

이것은 대의원을 그 자체로 설정하여 서비스 클래스가 호출되는 주요보기 클래스입니다. 또한 프로토콜은 헤더 클래스에서 구현됩니다.

@interface viewController: UIViewController <ServiceResponceDelegate>
{
ServiceClass* _service;
}

- (void) go;

@end

@implementation viewController

//
//some methods
//

- (void) go
{
_service = [[ServiceClass alloc] init];
[_service setDelegate:self];
[_service someTask];
}

이것이 바로이 클래스에서 대의원 방법을 구현함으로써 조작/작업이 완료되면 제어가 다시 시작됩니다.

부인 성명:이것이 Swift 버전을 만드는 방법 delegate.

그렇다면 대의원이란 무엇입니까?...소프트웨어 개발에는 주어진 상황에서 일반적으로 발생하는 문제를 해결하는 데 도움이 되는 일반적인 재사용 가능한 솔루션 아키텍처가 있습니다. 말하자면 이러한 "템플릿"은 디자인 패턴으로 가장 잘 알려져 있습니다.대리자는 특정 이벤트가 발생할 때 한 개체가 다른 개체에 메시지를 보낼 수 있도록 하는 디자인 패턴입니다.객체 A가 객체 B를 호출하여 작업을 수행한다고 상상해 보세요.작업이 완료되면 객체 A는 B가 작업을 완료했음을 알고 필요한 조치를 취해야 하며 이는 대리인의 도움으로 달성될 수 있습니다!

더 나은 설명을 위해 간단한 애플리케이션에서 Swift를 사용하여 클래스 간에 데이터를 전달하는 사용자 정의 대리자를 만드는 방법을 보여 드리겠습니다.이 시작 프로젝트를 다운로드하거나 복제하여 시작하고 실행해 보세요!

두 개의 클래스가 있는 앱을 볼 수 있습니다. ViewController A 그리고 ViewController B.B에는 탭 시 배경색을 변경하는 두 가지 보기가 있습니다. ViewController, 너무 복잡한 건 없지 않나요?이제 클래스 B의 뷰를 탭할 때 클래스 A의 배경색도 변경하는 쉬운 방법을 생각해 보겠습니다.

문제는 이 뷰가 클래스 B의 일부이고 클래스 A에 대해 전혀 모른다는 것입니다. 따라서 이 두 클래스 간에 통신할 수 있는 방법을 찾아야 하며 이것이 바로 위임이 빛나는 부분입니다.필요할 때 치트 시트로 사용할 수 있도록 구현을 6단계로 나누었습니다.

1 단계:ClassBVC 파일에서 pragma 마크 1단계를 찾아서 다음을 추가하세요.

//MARK: step 1 Add Protocol here.
protocol ClassBVCDelegate: class {
func changeBackgroundColor(_ color: UIColor?)
}

첫 번째 단계는 protocol, 이 경우 클래스 B에 프로토콜을 생성할 것이며, 프로토콜 내부에서는 구현 요구 사항에 따라 원하는 만큼 많은 기능을 생성할 수 있습니다.이 경우에는 선택 사항을 허용하는 하나의 간단한 함수만 있습니다. UIColor 논쟁으로.프로토콜 이름에 단어를 추가하는 것이 좋습니다. delegate 이 경우 클래스 이름 끝에 ClassBVCDelegate.

2 단계:pragma mark 2단계를 찾으세요. ClassVBC 그리고 이것을 추가하세요

//MARK: step 2 Create a delegate property here.
weak var delegate: ClassBVCDelegate?

여기서는 클래스에 대한 위임 속성을 생성합니다. 이 속성은 다음을 채택해야 합니다. protocol 유형이며 선택사항이어야 합니다.또한 유지 주기와 잠재적인 메모리 누수를 방지하려면 속성 앞에 약한 키워드를 추가해야 합니다. 이것이 무엇을 의미하는지 모른다면 지금은 걱정하지 말고 이 키워드를 추가하는 것을 기억하세요.

3단계:HandleTap 내부에서 pragma 마크 3단계를 찾으세요. method ~에 ClassBVC 그리고 이것을 추가하세요

//MARK: step 3 Add the delegate method call here.
delegate?.changeBackgroundColor(tapGesture.view?.backgroundColor)

알아야 할 한 가지 사항은 앱을 실행하고 아무 뷰나 탭하면 새로운 동작이 표시되지 않으며 이는 올바른 것입니다. 그러나 제가 지적하고 싶은 것은 대리자가 호출될 때 앱이 충돌하지 않는다는 것입니다. 이는 선택적 값으로 생성하기 때문이며 위임된 항목이 아직 존재하지 않아도 충돌이 발생하지 않는 이유입니다.이제 가보자 ClassAVC 파일을 작성하여 위임합니다.

4단계:handlerTap 메소드 내에서 pragma 마크 4단계를 찾으십시오. ClassAVC 다음과 같이 클래스 유형 옆에 추가하세요.

//MARK: step 4 conform the protocol here.
class ClassAVC: UIViewController, ClassBVCDelegate {
}

이제 ClassAVC는 ClassBVCDelegate 프로토콜을 사용하면 컴파일러에서 "'ClassAVC 유형은 'ClassBVCDelegate' 프로토콜을 따르지 않습니다. 이는 프로토콜의 메서드를 아직 사용하지 않았다는 의미일 뿐입니다. 클래스 A가 채택할 때를 상상해 보세요."라는 오류가 표시됩니다. 프로토콜은 클래스 B와 계약을 체결하는 것과 같으며 이 계약에는 "나를 채택하는 모든 클래스는 내 기능을 사용해야 합니다!"라고 명시되어 있습니다.

빠른 참고 사항:만약 당신이 다음 지역에서 왔다면 Objective-C 배경에서 여러분은 아마도 그 오류를 종료하여 해당 방법을 선택 사항으로 만들 수 있다고 생각할 것입니다. 그러나 놀랍게도 여러분도 마찬가지일 것입니다. Swift 언어는 선택 사항을 지원하지 않습니다 protocols, 원하는 경우 확장 프로그램을 만들 수 있습니다. protocol 또는 @objc 키워드를 사용하세요. protocol 구현.

개인적으로, 다른 선택적인 방법을 사용하여 프로토콜을 만들어야 한다면 나는 그것을 여러 부분으로 나누는 것을 선호합니다. protocols, 그런 식으로 객체에 하나의 단일 책임을 부여한다는 개념을 따르겠지만 이는 특정 구현에 따라 달라질 수 있습니다.

여기는 선택적 방법에 대한 좋은 기사입니다.

5단계:segue 메서드 준비 내에서 pragma mark 5단계를 찾아 이를 추가합니다.

//MARK: step 5 create a reference of Class B and bind them through the `prepareforsegue` method.
if let nav = segue.destination as? UINavigationController, let classBVC = nav.topViewController as? ClassBVC {
classBVC.delegate = self
}

여기서는 인스턴스를 생성하고 있습니다. ClassBVC 그리고 그 대리인을 self에게 할당합니다. 그러나 여기서 self는 무엇입니까?글쎄, 자아는 ClassAVC 위임된 것입니다!

6단계:마지막으로 pragma 6단계를 찾으세요. ClassAVC 그리고 다음의 기능을 사용해 보겠습니다. protocol, func를 입력해 보세요 변경배경색상 그러면 자동으로 완성되는 것을 볼 수 있습니다.그 안에 어떤 구현이라도 추가할 수 있습니다. 이 예에서는 배경색만 변경하고 이것을 추가하겠습니다.

//MARK: step 6 finally use the method of the contract
func changeBackgroundColor(_ color: UIColor?) {
view.backgroundColor = color
}

이제 앱을 실행해 보세요!

Delegates 어디에나 있으며 예고 없이 사용할 수도 있습니다. tableview 과거에는 위임을 사용했는데, 많은 클래스의 UIKIT 그들과 다른 많은 주변에서 작동합니다. frameworks 또한 이러한 주요 문제도 해결합니다.

  • 물체가 긴밀하게 결합되지 않도록 하십시오.
  • 객체를 하위 클래스로 분류할 필요 없이 동작과 모양을 수정합니다.
  • 작업이 임의의 개체로 처리되도록 허용합니다.

축하합니다. 방금 사용자 정의 대리자를 구현했습니다. 아마도 이것 때문에 너무 많은 문제가 있다고 생각하고 계실 것입니다.글쎄요, 위임은 당신이 관리자가 되고 싶다면 이해해야 할 매우 중요한 디자인 패턴입니다. iOS 개발자이며 객체 간에 일대일 관계가 있다는 점을 항상 명심하세요.

원본 튜토리얼을 보실 수 있습니다 여기

답변은 실제로 답변되지만 대의원을 만들기위한 "치트 시트"를 제공하고 싶습니다.

DELEGATE SCRIPT

CLASS A - Where delegate is calling function

@protocol <#Protocol Name#> <NSObject>

-(void)delegateMethod;

@end

@interface <#Some ViewController#> : <#UIViewController#> 

@property (nonatomic, assign) id <<#Protocol Name#>> delegate;

@end


@implementation <#Some ViewController#> 

-(void)someMethod {
    [self.delegate methodName];
}

@end




CLASS B - Where delegate is called 

@interface <#Other ViewController#> (<#Delegate Name#>) {}
@end

@implementation <#Other ViewController#> 

-(void)otherMethod {
    CLASSA *classA = [[CLASSA alloc] init];

    [classA setDelegate:self];
}

-delegateMethod() {

}

@end

ViewController.h

@protocol NameDelegate <NSObject>

-(void)delegateMEthod: (ArgType) arg;

@end

@property id <NameDelegate> delegate;

ViewController.m

[self.delegate delegateMEthod: argument];

MainViewController.m

ViewController viewController = [ViewController new];
viewController.delegate = self;

방법:

-(void)delegateMEthod: (ArgType) arg{
}

내 관점에서는 해당 대의원 방법에 대해 별도의 클래스를 만들고 원하는 곳에 사용할 수 있습니다.

내 사용자 정의 DropdownClass.h에서

typedef enum
{
 DDSTATE,
 DDCITY
}DropDownType;

@protocol DropDownListDelegate <NSObject>
@required
- (void)dropDownDidSelectItemWithString:(NSString*)itemString     DropDownType:(DropDownType)dropDownType;
@end
@interface DropDownViewController : UIViewController
{
 BOOL isFiltered;
}
@property (nonatomic, assign) DropDownType dropDownType;
@property (weak) id <DropDownListDelegate> delegate;
@property (strong, nonatomic) NSMutableArray *array1DropDown;
@property (strong, nonatomic) NSMutableArray *array2DropDown;

그 후 in.m 파일 객체가있는 배열을 만듭니다.

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
CGFloat rowHeight = 44.0f;
return rowHeight;
}

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return isFiltered?[self.array1DropDown count]:[self.array2DropDown count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = @"TableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}

if (self.delegate) {
    if (self.dropDownType == DDCITY) {
        cell.textLabel.text = [self.array1DropDown objectAtIndex:indexPath.row];
    }
    else if (self.dropDownType == DDSTATE) {
        cell.textLabel.text = [self.array2DropDown objectAtIndex:indexPath.row];
    }
}
return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
 [self dismissViewControllerAnimated:YES completion:^{
    if(self.delegate){
        if(self.dropDownType == DDCITY){
            [self.delegate dropDownDidSelectItemWithString:[self.array1DropDown objectAtIndex:indexPath.row] DropDownType:self.dropDownType];
        }
        else if (self.dropDownType == DDSTATE) {
            [self.delegate dropDownDidSelectItemWithString:[self.array2DropDown objectAtIndex:indexPath.row] DropDownType:self.dropDownType];
        }
    }
}];
}

여기에 모두 사용자 정의 대의원 클래스로 설정되어 있습니다.이 대의원 메소드를 원하는 위치에 사용할 수 있습니다. 예를 들어 ...

그 후 내 다른 뷰 콘트롤러 가져 오기

이와 같은 대의원을 호출하기위한 조치를 만듭니다

- (IBAction)dropDownBtn1Action:(id)sender {
DropDownViewController *vehicleModelDropView = [[DropDownViewController alloc]init];
vehicleModelDropView.dropDownType = DDCITY;
vehicleModelDropView.delegate = self;
[self presentViewController:vehicleModelDropView animated:YES completion:nil];
}

그 후에는 이와 같은 대의원 방법을 호출합니다

- (void)dropDownDidSelectItemWithString:(NSString *)itemString DropDownType:(DropDownType)dropDownType {
switch (dropDownType) {
    case DDCITY:{
        if(itemString.length > 0){
            //Here i am printing the selected row
            [self.dropDownBtn1 setTitle:itemString forState:UIControlStateNormal];
        }
    }
        break;
    case DDSTATE: {
        //Here i am printing the selected row
        [self.dropDownBtn2 setTitle:itemString forState:UIControlStateNormal];
    }

    default:
        break;
}
}

대의원 :- 생성

@protocol addToCartDelegate <NSObject>

-(void)addToCartAction:(ItemsModel *)itemsModel isAdded:(BOOL)added;

@end

보내 주시면 DELEGATE를 할당하십시오.

[self.delegate addToCartAction:itemsModel isAdded:YES];
//1.
//Custom delegate 
@protocol TB_RemovedUserCellTag <NSObject>

-(void)didRemoveCellWithTag:(NSInteger)tag;

@end

//2.
//Create a weak reference in a class where you declared the delegate
@property(weak,nonatomic)id <TB_RemovedUserCellTag> removedCellTagDelegate;

//3. 
// use it in the class
  [self.removedCellTagDelegate didRemoveCellWithTag:self.tag];

//4. import the header file in the class where you want to conform to the protocol
@interface MyClassUsesDelegate ()<TB_RemovedUserCellTag>

@end

// 5. 클래스에서 메소드를 구현하십시오 .m- (void) didremovecellwithTag : (nsinteger) tag {nslog@( "tag %d", tag);

}

예를 들어, 온라인으로 제품을 구매하는 경우 다른 팀이 처리하는 배송/배송과 같은 프로세스를 거치게됩니다. 따라서 배송이 완료되면 배송 팀은 배송 팀에 알리고이 정보를 방송하는 데 일대일 커뮤니케이션이어야합니다. 다른 사람 / 공급 업체는이 정보를 필요한 사람들에게만 전달하기를 원할 수 있습니다.

따라서 앱의 관점에서 생각하면 이벤트는 온라인 주문이 될 수 있으며 다른 팀은 여러 조회와 같을 수 있습니다.

다음은 배송 팀 및 배송 팀으로 배송 팀으로 배송하는 Code 고려 사항입니다.

//Declare the protocol with functions having info which needs to be communicated
protocol ShippingDelegate : class {
    func productShipped(productID : String)
}
//shippingView which shows shipping status of products
class ShippingView : UIView
{

    weak var delegate:ShippingDelegate?
    var productID : String

    @IBAction func checkShippingStatus(sender: UIButton)
    {
        // if product is shipped
        delegate?.productShipped(productID: productID)
    }
}
//Delivery view which shows delivery status & tracking info
class DeliveryView: UIView,ShippingDelegate
{
    func productShipped(productID : String)
    {
        // update status on view & perform delivery
    }
}

//Main page on app which has both views & shows updated info on product whole status
class ProductViewController : UIViewController
{
    var shippingView : ShippingView
    var deliveryView : DeliveryView

    override func viewDidLoad() {
        super.viewDidLoad()
        // as we want to update shipping info on delivery view, so assign delegate to delivery object
        // whenever shipping status gets updated it will call productShipped method in DeliveryView & update UI.
        shippingView.delegate = deliveryView
        //
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top