如何在Objective-C中创建委托?


Answers:


888

Objective-C委托是已分配给 delegate属性的对象。要创建一个,您需要定义一个实现您感兴趣的委托方法的类,并将该类标记为实现委托协议。

例如,假设您有一个UIWebView。如果您想实现其委托人的webViewDidStartLoad:方法,则可以创建这样的类:

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

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

然后,您可以创建MyClass的实例,并将其分配为Web视图的委托:

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

UIWebView一侧,它可能具有与此类似的代码,以查看委托是否webViewDidStartLoad:使用响应消息respondsToSelector:并在适当时发送消息。

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

通常weak(在ARC中)或(在ARC之前)声明委托属性本身,assign以避免保留循环,因为对象的委托通常持有对该对象的强引用。(例如,视图控制器通常是它包含的视图的委托。)

为您的班级派代表

要定义自己的委托,您必须在某个地方声明他们的方法,如关于协议Apple Docs所述。您通常会声明一个正式协议。从UIWebView.h释义的声明如下所示:

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

UIWebViewDelegate在这种情况下,这类似于接口或抽象基类,因为它为您的委托创建了特殊类型。委托实现者必须采用以下协议:

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

然后实现协议中的方法。对于在协议中声明为的方法@optional(与大多数委托方法一样),您需要-respondsToSelector:在调用特定方法之前先进行检查。

命名

委托方法通常以委托类名称开头,并以委托对象作为第一个参数。他们还经常使用遗嘱,应有或惯用的形式。因此,例如webViewDidStartLoad:(第一个参数是Web视图)而不是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(这使自动完成功能变得不那么有用),并且使编译器很难向您发出错别字和类似错误的警告。


我认为您需要将unsigned int类型强制转换BOOLdelegate respondsToSelectoris 的返回值BOOL
罗兰

可以像C ++中那样将委托用于多态吗?

@丹是的,当然。协议通常用于多态。
杰西·鲁萨克

@JesseRusak我认为“ JSSomethingDelegate”应为“ SomethingDelegate”以确保一致性:)
HansKnöchel17年

382

批准的答案很好,但是如果您要寻找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

在另一个类(在这种情况下,UIViewController称为MyVC)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!");
}

4
很好使用此答案作为快速参考。但是,为什么MyClass.h中的委托属性标记为“ IBOutlet”?
Arno van der Meer

4
@ArnovanderMeer好抓住!我不记得为什么。我在项目中需要它,但在本示例中不需要,因此将其删除。thx
Tibidabo

谢谢。尽管已获得公认的答案,但它很好而透彻,我从一些紧凑的示例代码中学到了很多。有两个答案很好。
sudo 2014年

@Tibidabo十分出色。我真的希望每个人都能解释这样的编程概念。多年来,我已经看到了数百种关于“代理人”的解释,并且直到现在为止还没有真正掌握过这种理论!非常感谢...
Charles Robertson

5
myClassMyVC.m中实例化的位置是什么?
莱蒂希巷

18

使用正式协议方法创建委托支持时,我发现您可以通过添加以下内容来确保正确的类型检查(尽管是运行时,而不是编译时):

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

在您的委托访问器(setDelegate)代码中。这有助于最大程度地减少错误。


18

请!请查看以下简单的分步教程,了解Delegates如何在iOS中工作。

在iOS中委托

我创建了两个ViewController(用于将数据从一个发送到另一个)

  1. FirstViewController实现委托(提供数据)。
  2. SecondViewController声明委托(它将接收数据)。

17

也许这更符合您所缺少的内容:

如果您来自像C ++这样的观点,则代表需要一点时间来适应-但基本上“它们是行得通的”。

它的工作方式是将一些作为委托编写的对象设置为NSWindow,但是您的对象只有许多可能的委托方法中的一种或几种的实现(方法)。所以发生了一些事情,NSWindow想要调用您的对象-它只是使用Objective-c的respondsToSelector方法来确定您的对象是否要调用该方法,然后再调用它。这就是Objective-C的工作方式-按需查找方法。

用您自己的对象执行此操作非常简单,没有什么特别的事情,例如,您可以拥有NSArray27个对象中的一个,所有不同类型的对象,其中只有18个对象具有-(void)setToBue;其他9个方法。因此,调用setToBlue18个需要完成的任务,如下所示:

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

关于委托的另一件事是不保留委托,因此您始终必须nilMyClass dealloc方法中将委托设置为。


15

作为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视图(符合您的委托)是否实际实现了可选方法。


11

我认为,一旦您了解了代表,所有这些答案就很有意义了。就我个人而言,我来自C / C ++领域,在此之前像是Fortran等程序语言,所以这是我2分钟的时间,打算在C ++范例中找到类似的类似物。

如果我要向C ++ / Java程序员解释委托,我会说

什么是代表?这些是指向另一个类中的类的静态指针。一旦分配了指针,就可以在该类中调用函数/方法。因此,您的类的某些功能被“委托”(在C ++世界中-由类对象指针指向)到另一个类。

什么是协议?从概念上讲,它的作用类似于您要分配为委托类的类的头文件。协议是一种明确的方法,用于定义需要在类中将谁的指针设置为类中的委托的类中实现的方法。

我如何在C ++中做类似的事情?如果尝试在C ++中执行此操作,则可以通过在类定义中定义指向类(对象)的指针,然后将它们连接到其他类,这些其他类将提供附加功能作为基类的委托。但是这种接线需要在代码中进行,并且笨拙且容易出错。目标C只是假设程序员并不擅长于保持这一准则,并提供了编译器限制以执行干净的实现。


您在说的是我在说直觉时的语义。您所谈论的是虚拟功能-但要习惯于新术语可能会充满挑战。答案适用于想在C ++ / C中实现并行处理的
初学者

你说的对我来说不是很清楚。您为什么不写一个新的答复,然后看看是否有更多的人觉得它有用,他们会投票赞成?
DrBug 2014年

9

迅捷版

委托只是一个为另一个类做一些工作的类。阅读以下代码,获得一个有点愚蠢(但希望能启发人心)的Playground示例,该示例演示如何在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. 当一个班级想要允许另一个班级对其进行自定义时

这些类无需事先了解彼此,除了委托类符合所需的协议。

我强烈建议阅读以下两篇文章。他们帮助我比文档更好地理解了代表。


8

好的,这并不是对这个问题的真正答案,但是,如果您正在寻找如何创建自己的代表的方法,那么也许简单得多的方法对您来说是一个更好的答案。

我几乎没有实现我的代表,因为我很少需要。对于一个委托对象,我只能有一个委托。因此,如果您希望委托人以一种方式进行通信/传递数据,则比使用通知要好得多。

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

8

假设您有一个自己开发的类,并且想声明一个委托属性,以便在发生某些事件时可以通知它:

@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实例,因此,如果您将委托声明为retain,则两者将彼此保留,并且两者都不保留它们中的任何一个都将被释放)。

您还会注意到协议方法将MyClass实例作为参数传递给委托,这是最佳做法,以防委托要在MyClass实例上调用某些方法,并且当委托将自己声明为MyClassDelegate多个对象时也有帮助MyClass实例时也有,例如当您拥有多个实例时UITableView's实例,ViewController并将其声明为UITableViewDelegate所有实例。

在你里面 MyClass将声明的事件通知给代理,如下所示:

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

您首先要检查您的委托人是否响应您要调用的协议方法,以防该委托人未实现该方法,并且该应用程序将因此崩溃(即使需要该协议方法)。


6

这是创建委托的简单方法

在.h文件中创建协议。确保在协议之前使用@class定义该名称,后跟UIViewController的名称< As the protocol I am going to use is UIViewController class>.

步骤1:创建一个名为“ YourViewController”的新类协议,它将作为UIViewController类的子类,并将该类分配给第二个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]; 
     }
  }

5

要创建自己的委托,首先需要创建一个协议并声明必要的方法,而无需实现。然后将此协议实现到您要实现委托或委托方法的标头类中。

协议必须声明如下:

@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];
}

就是这样,通过在此类中实现委托方法,一旦操作/任务完成,控制权就会返回。


4

免责声明:这是Swift如何创建的版本delegate

那么,代表是什么?…在软件开发中,有通用的可重用解决方案体系结构可帮助解决给定上下文中常见的问题,可以说这些“模板”被称为设计模式。委托是一种设计模式,当特定事件发生时,该模式允许一个对象向另一个对象发送消息。想象一下,对象A调用对象B来执行操作。一旦动作完成,对象A应该知道B已完成任务并采取必要的动作,这可以在代表的帮助下实现!

为了获得更好的解释,我将向您展示如何创建一个自定义委托,该委托在简单的应用程序中使用Swift在类之间传递数据,首先下载或克隆此启动程序并运行它!

你可以看到一个应用程序有两个班,ViewController AViewController B。B有两种观点,点击可改变的背景颜色ViewController,没有什么太复杂了吧?好了,现在让我们以一种简单的方式来考虑,当点击B类的视图时,它也可以更改A类的背景颜色。

问题在于该视图是B类的一部分,对A类不了解,因此我们需要找到一种在这两个类之间进行通信的方法,这就是授权的亮点。我将实现分为6个步骤,因此您可以在需要时将其用作备忘单。

步骤1:在ClassBVC文件中查找步骤1的实用标记并将其添加

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

第一步是创建一个protocol,在这种情况下,我们将在B类中创建协议,在该协议内,您可以根据实现的要求创建任意数量的函数。在这种情况下,我们只有一个简单的函数,它接受可选UIColor参数作为参数。命名协议的一种好习惯delegate是在类名的末尾添加单词(在本例中为)ClassBVCDelegate

步骤2:寻找步骤2中的实用标记,ClassVBC然后添加

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

在这里,我们只为类创建一个委托属性,该属性必须采用protocol类型,并且应该是可选的。另外,您应该在属性之前添加weak关键字,以避免保留周期和潜在的内存泄漏,如果您不知道那意味着什么现在就不用担心,只需记住添加此关键字即可。

第3步:查找有关编译标记步骤3中的handleTap内methodClassBVC和添加此

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

您应该知道的一件事,运行该应用程序并点击任意视图,您将看不到任何新行为,这是正确的,但是我要指出的是,调用委托时该应用程序不会崩溃,并且这是因为我们将其创建为可选值,因此即使委托不存在它也不会崩溃。现在让我们进行ClassAVC归档并进行委派。

步骤4:在handleTap方法中查找步骤4的杂用标记,ClassAVC并将其添加到您的类类型旁边,如下所示。

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

现在,ClassAVC采用了该ClassBVCDelegate协议,您可以看到编译器给您一个错误,指出“类型'ClassAVC不符合协议'ClassBVCDelegate”,这仅意味着您尚未使用协议的方法,请想象一下当A类采用该协议时,就像与B类签订合同,并且该合同说:“任何采用我的类都必须使用我的功能!”

快速说明:如果您来自Objective-C背景,您可能会认为您也可以关闭该错误,使该方法成为可选方法,但是令我惊讶的是,您的Swift语言可能不支持可选方法,令您感到意外的是,protocols您可以创建该方法的扩展名,protocol或在protocol实现中使用@objc关键字。

就个人而言,如果我必须使用不同的可选方法来创建协议,则我希望将其分解为不同的协议protocols,那样,我将遵循为对象赋予单一责任的概念,但是它会根据具体实现而有所不同。

这是一篇关于可选方法的好文章。

步骤5:在“准备缝制”方法中查找步骤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:最后,在步骤6中寻找实用性ClassAVC让我们使用的功能protocol,开始输入func changeBackgroundColor,您会发现它会自动为您完成。您可以在其中添加任何实现,在此示例中,我们只需更改背景色,然后添加即可。

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

现在运行该应用程序!

Delegates到处都是,您可能甚至tableview在没有通知的情况下使用它们,如果您过去创建了委托,那么UIKIT围绕它们的许多类工作以及许多其他工作frameworks,它们就可以解决这些主要问题。

  • 避免物体紧密结合。
  • 无需子类化对象即可修改行为和外观。
  • 允许将任务处理到任意对象。

恭喜,您只实现了一个自定义委托,我知道您可能在想,为此有那么多麻烦吗?好的,委派是一种非常重要的设计模式,可以理解您是否想成为一名iOS开发人员,并始终牢记对象之间具有一对一的关系。

您可以在这里看到原始教程


4

答案实际上是答案,但是我想给您一个创建代表的“备忘单”:

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

2

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

2

以我的观点,为该委托方法创建单独的类,您可以在需要的地方使用。

在我的自定义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];
        }
    }
}];
}

这里所有的都是为Custom委托类设置的。之后,您可以在需要的地方使用此委托方法,例如...

在我的另一个viewcontroller导入之后

创建调用这样的委托方法的动作

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

0

代表:-创建

@protocol addToCartDelegate <NSObject>

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

@end

发送并请指派代表查看您正在发送数据

[self.delegate addToCartAction:itemsModel isAdded:YES];

0
//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);中实现该方法。

}


0

让我们从一个例子开始,如果我们在线购买产品,它会经历由不同团队处理的运输/交付过程。因此,如果运输完成,则运输团队应通知交付团队,并且应该以一对一的方式传播此信息。对于其他人来说将是开销/供应商可能只希望将此信息传递给所需人员。

因此,如果我们从应用程序角度考虑,那么事件可以是在线订单,而不同的团队可能就像是多个视图。

这是将ShippingView视为发运团队并将DeliveryView视为交付团队的代码:

//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
        //
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.