iOS开发中,界面之间传递消息或者数据是最基本的一种需求,我们可以使用很多方法来实现这种需求,比如在头文件中暴露一个属性、比如使用notification(一对多的消息传递)等等。今天我们要来介绍另一种方式:使用delegate传递消息(一对一的消息传递)。
delegate称为委托,同时也是一种代理设计模式。使用委托避免了类与类的耦合度过高。利用委托赋值更加安全可控,委托赋值在不暴露自己类的属性的前提下就可以对自己进行赋值。
在iOS中委托通过协议@protocol来实现,在协议中所声明的方法,不需要在协议中有实现的方法,是由它的实现类来实现(该类需要在头文件中包含<协议名>)。“协议”和“委托”是两个不一样的概念,因为我们在看代码的时候总是会看到他们出现在一起。但不能说,delegate就是protocol,delegate是一种架构模式。举个例子什么是“委托”:比如我在开车,但是开车不能看短信,所以我就叫车里的朋友帮我看短信,这样我就可以正常的开车了。当朋友看完短信内容后,就告诉我是什么内容。这就是委托,朋友就是我的委托对象。“协议”protocol是用来定义对象的属性和行为,类似于C++中的虚函数。其中有两个关键字@required和@optional,前者表示必须要实现的方法,后者是可选的方法。
使用delegate常用在两种情况下:
*两个类之间的传值,类A调用类B的方法,类B在执行过程中遇到问题通知类A;
*控制器(ViewController)与控制器(ViewController)之间的传值,从A跳转到B,再从B返回到A时需要通知A更新UI或者是做其他的事情,这时候就用到了代理(delegate)传值。
tips:如果没有在@protocol中显式的写上@required或者@optional,那么默认就是@required(必需的)的。为了不引起歧义,最好显式的写上@required或@optional。
通常一个delegate的使用过程需要经过5步:
(1)创建一个delegate;
(2)委托者声明一个delegate;
(3)委托者调用delegate内的方法(method);
(4)被委托者设置delegate,以便被委托者调用;
(5)被委托者实现delegate所定义的方法;
下面我通过1个实例来演示使用delegate传递数据,代码上传至:https://github.com/chenyufeng1991/iOS-Delegate 中的Delegate01.
(1)首先程序是基于storyboard来构建的,界面布局如下:在界面返回的时候将会传递数据。
。
(2)新建一个Protocol,作为我们的协议,里面可以声明一些方法。如图:
ProtocolDelegate里面的实现如下:
#import <Foundation/Foundation.h> //实现一个protocol; /** * 可以理解为Java中的接口interface; */ @protocol ProtocolDelegate <NSObject> // 必须实现的方法 @required - (void)execute; // 可选实现的方法 @optional - (void)function1; - (void)function2; - (void)function3; @end
#import <UIKit/UIKit.h> // 新建一个协议,协议的名字一般是由“类名+Delegate” /** * 在该协议中声明的方法,在第一个界面中实现,在该界面中调用; */ @protocol ViewControllerBDelegate <NSObject> @required - (void)sendValue:(NSString *)value; @end @interface ViewControllerB : UIViewController //这里的delegate要设置在.h中; @property (weak, nonatomic) id<ViewControllerBDelegate> delegate; @end
#import "ViewControllerB.h" //第二个界面; @interface ViewControllerB () @property (strong, nonatomic) IBOutlet UITextField *textField; @end @implementation ViewControllerB - (IBAction)backAction:(id)sender{ //界面跳转的时候调用该方法; [self.delegate sendValue:self.textField.text]; // 通知执行协议方法 //返回传递消息; [self.navigationController popViewControllerAnimated:YES]; } @end
#import "ViewController.h" #import "ProtocolDelegate.h" #import "ViewControllerB.h" //第一个界面; @interface ViewController () <ProtocolDelegate, ViewControllerBDelegate> @end @implementation ViewController //因为是基于storyboard的segue来构建,当界面跳转时,自动回调该方法; - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ ViewControllerB *vc = segue.destinationViewController; [vc setDelegate:self]; } // 这里实现B控制器的协议方法 - (void)sendValue:(NSString *)value{ UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"成功" message:value delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; [alertView show]; } //该方法是ProtocolDelegate中的@required方法; - (void)execute{ } - (IBAction)pressed:(id)sender { NSLog(@"1111"); } @end
上面的demo是基于storyboard。由于有些项目是基于nib文件构建的,我下面来演示一下使用nib文件时的注意点。代码在:https://github.com/chenyufeng1991/iOS-Delegate 中的Delegate02.
(1)删除原来的main.storyboard,新增两个nib文件,分别绑定对应的ViewController。我推荐使用navigationBar,所以在AppDelegate.m中的实现如下:
#import "AppDelegate.h" #import "ViewController.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.rootViewController = [[ViewController alloc] init]; self.naviController = [[UINavigationController alloc] initWithRootViewController:self.window.rootViewController]; [self.window addSubview:self.naviController.view]; [self.window makeKeyAndVisible]; return YES; } @end
- (IBAction)pressed:(id)sender { //如果项目本身是根据nib文件构建的,就使用下面的方式绑定delegate,并跳转; ViewControllerB *vb = [[ViewControllerB alloc] initWithNibName:@"ViewControllerB" bundle:[NSBundle mainBundle]]; vb.delegate = self; [self.navigationController pushViewController:vb animated:true]; }
然后运行效果同上。不同之处也就是在ViewController绑定delegate处有不同。
总结,Delegate委托属于程序架构层面上,是相对比较高的层次,如果我们能够熟练使用delegate,就能有效降低程序耦合度,提高代码可读性。
本文参考:http://blog.csdn.net/shenjie12345678/article/details/24555973
http://leopard168.blog.163.com/blog/static/168471844201307112149221/
http://www.cocoachina.com/ios/20150112/10880.html
github主页:https://github.com/chenyufeng1991 。欢迎大家访问!