在.NET中都知道委托(delegate),通俗点的解释就是可以将方法作为一个参数传到另外一个方法中使用。
委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和返回值。在Object C中也同样存在委托的概念,但是委托一般与协议(Protocol)同时使用,而且和.NET中的委托稍有区别
一. 定义委托(delegate)先定义一个协议(Protocol)
回顾一下上一篇所学的,先定义一个协议(Protocol) ProtocolName, 协议ProtocolName中定义了两个方法: first ,second
具体的代码如下:
#import <Foundation/Foundation.h> @protocol ProtocolName <NSObject> -(void) first; -(void) second; @end
上面定义的协议包含了两个方法,返回值类型为特殊的类型void 。 void 在Object C中也被认为是一种特殊的返回值类型。
二. 定义两个类遵循协议并实现方法
现在这里定义两个类StudentA和StudentB来实现协议ProtocolName中的方法.
StudentA 实现的代码如下:
#import <Foundation/Foundation.h> #import "ProtocolName.h" @interface StudentA : NSObject<ProtocolName> @end =============================================== #import "StudentA.h" @implementation StudentA -(void) first{ NSLog(@"StudentA---first"); } -(void) second{ NSLog(@"StudentA--second"); } @end
StudentB实现代码如下:
#import <Foundation/Foundation.h> #import "ProtocolName.h" @interface StudentB : NSObject <ProtocolName> @end ------------------------------------------------------------ #import "StudentB.h" @implementation StudentB -(void) first{ NSLog(@"StudentB--first"); } -(void) second{ NSLog(@"StudentB--second"); } @end
我们注意到协议ProtocolName中的两个方法并没有使用@required 或者@optional 来修饰, 前面也提到过了,如果没有使用任何修饰那么默认是@required,那么StudentA和StudentB必须实现这两个方法,否则在编译的时候就报错。
三. 定义一个类用于代理
在上面定义了一个协议ProtocolName,然后新建一个Object C类Student,但是这个类并没有去遵循协议ProtocolName 去实现其他的方法,而是通过委托来代理实现协议方法的调用。定义委托和定义属性一样,Student中的代理属性代码实现如下:
#import <Foundation/Foundation.h> #import "ProtocolName.h" @interface Student : NSObject{ id<ProtocolName> delegate; } @property (retain) id<ProtocolName> delegate; -(void) setMethod; @end --------------------------------------------- #import "Student.h" @implementation Student @synthesize delegate; -(void) setMethod{ NSLog(@"Student---setMethod"); [delegate first]; [delegate second]; } @end
在Student.h中定义了 id<ProtocolName> delegate; 这个其实就是类中的属性,后来使用@property来修饰说明其自动实现了get set方法。这里不多说。关键看如何使用:
先创建一个 StudentA 的实例,同时创建一个 Student 的实例, 将 StudentA 的实例赋值给 delegate,这里相当于 delegate 代理了 StudentA 的实例。
Student *stu=[[Student alloc] init]; StudentA *stua=[[StudentA alloc] init]; StudentB *stub=[[StudentB alloc] init]; stu.delegate=stua; [stu.delegate first]; [stu setMethod]; stu.delegate=stub; [stu setMethod];
看到上面的代码 stu.delegate=stua, 这个就是委托代理。当 stu 调用方法 setMethod 方法时候,使用委托调用了方法 first 和方法 second。
而代码 stu.delegate=stub, delegate 又代理 stub 类,可以调用其中的方法 first,second .
上面的测试结果如下:
2014-03-21 22:45:07.870 DelegateOS[577:303] StudentA---first 2014-03-21 22:45:07.872 DelegateOS[577:303] Student---setMethod 2014-03-21 22:45:07.872 DelegateOS[577:303] StudentA---first 2014-03-21 22:45:07.872 DelegateOS[577:303] StudentA--second 2014-03-21 22:45:07.873 DelegateOS[577:303] Student---setMethod 2014-03-21 22:45:07.873 DelegateOS[577:303] StudentB--first 2014-03-21 22:45:07.874 DelegateOS[577:303] StudentB--second
PS:
- 作用:提供成员变量的访问方法的声明、控制成员变量的访问权限、控制多线程时成员变量的访问环境。
- 使用范围:property不但可以在interface,在协议protocol和类别category中也可以使用。
- 作用:实现 property 所声明的方法的定义。其实说直白就像是:property 声明了一些成员变量的访问方法,synthesize 则定义了由 property 声明的方法。
- 他们之前的对应关系是: property 声明方法 ->头文件中申明 getter 和 setter 方法 synthesize 定义方法 -> m文件中实现 getter 和 setter 方法。