什么是代理?
苹果的官方文档给了很清晰的解释:
Delegation is a simple and powerful pattern in which one object in a program acts on behalf of, or in coordination with, another object. The delegating object keeps a reference to the other object—the delegate—and at the appropriate time sends a message to it. The message informs the delegate of an event that the delegating object is about to handle or has just handled. The delegate may respond to the message by updating the appearance or state of itself or other objects in the application, and in some cases it can return a value that affects how an impending event is handled. The main value of delegation is that it allows you to easily customize the behavior of several objects in one central object.
意译一下就是:代理是一种简单而功能强大的设计模式,这种模式用于一个对象“代表”另 外一个对象和程序中其他的对象进行交互。 主对象(这里指的是delegating object)中维护一个代理(delegate)的引用并且在合适的时候向这个代理发送消息。这个消息通知“代理”主对象即将处理或是已经处理完了某一 个事件。这个代理可以通过更新自己或是其它对象的UI界面或是其它状态来响应主对象所发送过来的这个事件的消息。或是在某些情况下能返回一个值来影响其它 即将发生的事件该如何来处理。代理的主要价值是它可以让你容易的定制各种对象的行为。注意这里的代理是个名词,它本身是一个对象,这个对象是专门代表被代 理对象来和程序中其他对象打交道的。
Protocol(协议)只能定义公用的一套接口,但不能提供具体的实现方法。也就是说,它只告诉你要做什么,但具体怎么做,它不关心。
当 一个类要使用某一个Protocol(协议)时,都必须要遵守协议。比如有些必要实现的方法,你没有去实现,那么编译器就会报警告,来提醒你没有遵守×× 协议。注意,我这里说的是警告,而不是错误。对的,就算你不实现那些“必要实现”的方法,程序也是能运行的,只不过多了些警告。
Protocol(协议)的作用:
1. 定义一套公用的接口(Public)
-
@required:必须实现的方法
-
@optional:可选 实现的方法(可以全部都不实现)
2. 委托代理(Delegate)传值:
它本身是一个设计模式,它的意思是委托别人去做某事。
比如:两个类之间的传值,类A调用类B的方法,类B在执行过程中遇到问题通知类A,这时候我们需要用到代理(Delegate)。
又比如:控制器(Controller)与控制器(Controller)之间的传值,从C1跳转到C2,再从C2返回到C1时需要通知C1更新UI或者是做其它的事情,这时候我们就用到了代理(Delegate)传值。
一、定义一套公用的接口(Public)
首先新建一个协议文件:
填上协议文件名及文件类型(选择Protocol):
ProtocolDelegate.h代码(协议不会生成.m文件):
#import @protocol ProtocolDelegate // 必须实现的方法 @required - (void)error; // 可选实现的方法 @optional - (void)other; - (void)other2; - (void)other3; @end
在需要使用到协议的类,import它的头文件:
#import "ViewController.h" #import "ProtocolDelegate.h"
我这里选择的是入口文件
记得要遵守协议:
@interface ViewController () @end
这时会报一个警告,因为定义的协议里有一个是必须实现的方法,而我们没有去实现:
实现了必须实现的方法后,编译器就不会报警告了:
至于其它的可选方法,你可以选择实现,也可以全都不实现。
二、委托代理(Delegate)传值
在Storyboard上,先搭好界面,如下图:
新建ControllerB:
把B界面的类设置为ViewControllerB:
下面放出主要类文件代码,我在里面写了注释,大家应该能看懂。不懂也没有关系,我会在本文结尾放上Demo下载地址。
ViewController.m文件:
1 #import "ViewController.h" 2 #import "ProtocolDelegate.h" 3 #import "ViewControllerB.h" 4 @interface ViewController () @end 5 @implementation ViewController 6 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 7 { 8 ViewControllerB *vc = segue.destinationViewController; 9 [vc setDelegate:self]; 10 } 11 // 这里实现B控制器的协议方法 12 - (void)sendValue:(NSString *)value 13 { 14 UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"成功" message:value delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; 15 [alertView show]; 16 } 17 - (void)error 18 { 19 } 20 @end
ViewControllerB.h文件:
1 #import // 新建一个协议,协议的名字一般是由“类名+Delegate” 2 @protocol ViewControllerBDelegate // 代理传值方法 3 - (void)sendValue:(NSString *)value; 4 5 @end 6 7 @interface ViewControllerB : UIViewController 8 9 // 委托代理人,代理一般需使用弱引用(weak) 10 @property (weak, nonatomic) id delegate; 11 12 @end
ViewControllerB.m文件:
1 #import "ViewControllerB.h" 2 @interface ViewControllerB () 3 @property (strong, nonatomic) IBOutlet UITextField *textField; 4 @end 5 @implementation ViewControllerB 6 - (IBAction)backAction:(id)sender 7 { 8 if ([_delegate respondsToSelector:@selector(sendValue:)]) { // 如果协议响应了sendValue:方法 9 [_delegate sendValue:_textField.text]; // 通知执行协议方法 10 } 11 [self.navigationController popViewControllerAnimated:YES]; 12 } 13 @end
完成效果截图:
小结:
当你需要定义一套公用的接口,实现方法可以是不同的时候,你可以使用Protocol协议。
当你需要进行类与类之间的传值时,你也可以基于Protocol协议,使用代理设计模式进行传值。