欢迎来到 IT实训基地-南通科迅教育
咨询电话:0513-81107100
iOS开发——使用delegate进行消息传递
2017/4/7
南通科迅教育
423
南通IT培训中心怎么选

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里面的实现如下:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#import<foundation foundation.h="">
 
//实现一个protocol;
/**
 *  可以理解为Java中的接口interface;
 */
@protocolProtocolDelegate <nsobject>
 
// 必须实现的方法
@required
- (void)execute;
 
// 可选实现的方法
@optional
- (void)function1;
- (void)function2;
- (void)function3;
 
@end</nsobject></foundation>


 

(3)我首先来实现第二个界面,在第二个界面的头文件.h中需要声明一个protocol,在该protocol中声明的方法可以在第一个界面中实现,并在第二个界面中进行调用。这是数据传递的关键。

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#import<uikit uikit.h="">
 
// 新建一个协议,协议的名字一般是由“类名+Delegate”
/**
 *  在该协议中声明的方法,在第一个界面中实现,在该界面中调用;
 */
@protocolViewControllerBDelegate <nsobject>
 
@required
- (void)sendValue:(NSString *)value;
 
@end
 
@interfaceViewControllerB : UIViewController
 
//这里的delegate要设置在.h中;
@property(weak, nonatomic) id<viewcontrollerbdelegate> delegate;
 
@end</viewcontrollerbdelegate></nsobject></uikit>

(4)在第二个界面的实现文件中实现如下:在点击返回键的时候调用协议中的方法,

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#import"ViewControllerB.h"
 
//第二个界面;
@interfaceViewControllerB ()
 
@property(strong, nonatomic) IBOutlet UITextField *textField;
 
@end
 
@implementationViewControllerB
 
- (IBAction)backAction:(id)sender{
 
  //界面跳转的时候调用该方法;
  [self.delegate sendValue:self.textField.text];// 通知执行协议方法
  //返回传递消息;
  [self.navigationController popViewControllerAnimated:YES];
}
 
@end

(5)下面来实现第一个界面ViewController.m:

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#import"ViewController.h"
#import"ProtocolDelegate.h"
#import"ViewControllerB.h"
 
//第一个界面;
@interfaceViewController () <protocoldelegate, viewcontrollerbdelegate="">
 
@end
 
@implementationViewController
 
//因为是基于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</protocoldelegate,>

(6)运行效果如下:

 

\

 

\

 

上面的demo是基于storyboard。由于有些项目是基于nib文件构建的,我下面来演示一下使用nib文件时的注意点。

(1)删除原来的main.storyboard,新增两个nib文件,分别绑定对应的ViewController。我推荐使用navigationBar,所以在AppDelegate.m中的实现如下:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#import"AppDelegate.h"
#import"ViewController.h"
 
@interfaceAppDelegate ()
 
@end
 
@implementationAppDelegate
 
- (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];
 
 
  returnYES;
}
 
@end

(2)在第二个界面中主要修改如下,删除prepareForSegue方法,在按钮的点击方法中实现:

 

 

?
1
2
3
4
5
6
7
8
- (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,就能有效降低程序耦合度,提高代码可读性。!

77
关闭
先学习,后交费申请表
每期5位名额
在线咨询
免费电话
QQ联系
先学习,后交费
TOP
您好,您想咨询哪门课程呢?
关于我们
机构简介
官方资讯
地理位置
联系我们
0513-91107100
周一至周六     8:30-21:00
微信扫我送教程
手机端访问
南通科迅教育信息咨询有限公司     苏ICP备15009282号     联系地址:江苏省南通市人民中路23-6号新亚大厦三楼             法律顾问:江苏瑞慈律师事务所     Copyright 2008-