iOS代理设计模式

来源:互联网 发布:南泥湾种鸦片 知乎 编辑:程序博客网 时间:2024/05/21 10:58

在iOS中有很多种消息传递方式,这里先简单介绍一下各种消息传递方式。

  • 通知:在iOS中由通知中心进行消息接收和消息广播,是一种一对多的消息传递方式。

  • 代理:是一种通用的设计模式,iOS中对代理支持的很好,由代理对象、委托者、协议三部分组成。

  • block:iOS4.0中引入的一种回调方法,可以将回调处理代码直接写在block代码块中,看起来逻辑清晰代码整齐。

  • target action:通过将对象传递到另一个类中,在另一个类中将该对象当做target的方式,来调用该对象方法,从内存角度来说和代理类似。

  • KVO:NSObject的Category-NSKeyValueObserving,通过属性监听的方式来监测某个值的变化,当值发生变化时调用KVO的回调方法。

代理是一种通用的设计模式,在iOS中对代理设计模式支持的很好,有特定的语法来实现代理模式,OC语言可以通过@Protocol实现协议。

代理主要由三部分组成:

  • 协议:用来指定代理双方可以做什么,必须做什么。

  • 代理:根据指定的协议,完成委托方需要实现的功能。

  • 委托:根据指定的协议,指定代理去完成什么功能。

协议有两个修饰符@optional和@required,创建一个协议如果没有声明,默认是@required状态的。这两个修饰符只是约定代理是否强制需要遵守协议,如果@required状态的方法代理没有遵守,会报一个黄色的警告,只是起一个约束的作用,没有其他功能。

无论是@optional还是@required,在委托方调用代理方法时都需要做一个判断,判断代理是否实现当前方法,否则会导致崩溃。

// 判断代理对象是否实现这个方法,没有实现会导致崩溃if ([self.delegate respondsToSelector:@selector(userLoginWithUsername:password:)]) {    [self.delegate userLoginWithUsername:self.username.text password:self.password.text];}



示例:假设我在公司正在敲代码,敲的正开心呢,突然口渴了,想喝一瓶红茶。这时我就可以拿起手机去外卖app上定一个红茶,然后外卖app就会下单给店铺并让店铺给我送过来。

这个过程中,外卖app就是我的代理,我就是委托方,我买了一瓶红茶并付给外卖app钱,这就是购买协议。我只需要从外卖app上购买就可以,具体的操作都由外卖app去处理,我只需要最后接收这瓶红茶就可以。我付的钱就是参数,最后送过来的红茶就是处理结果。

但是我买红茶的同时,我还想吃一份必胜客披萨,我需要另外向必胜客app去订餐,上面的外卖app并没有这个功能。我又向必胜客购买了一份披萨,必胜客当做我的代理去为我做这份披萨,并最后送到我手里。这就是多个代理对象,我就是委托方。


在iOS中一个代理可以有多个委托方,而一个委托方也可以有多个代理。我指定了外卖app和必胜客两个代理,也可以再指定麦当劳等多个代理,委托方也可以为多个代理服务。

代理对象在很多情况下其实是可以复用的,可以创建多个代理对象为多个委托方服务,在下面将会通过一个小例子介绍一下控制器代理的复用。

下面是一个简单的代理:

首先定义一个协议类,来定义公共协议

#import@protocol LoginProtocol@optional- (void)userLoginWithUsername:(NSString *)username password:(NSString *)password;@end定义委托类,这里简单实现了一个用户登录功能,将用户登录后的账号密码传递出去,有代理来处理具体登录细节。#import #import "LoginProtocol.h"/** *  当前类是委托类。用户登录后,让代理对象去实现登录的具体细节,委托类不需要知道其中实现的具体细节。 */@interface LoginViewController : UIViewController// 通过属性来设置代理对象@property (nonatomic, weak) id delegate;@end实现部分:@implementation LoginViewController- (void)loginButtonClick:(UIButton *)button {  // 判断代理对象是否实现这个方法,没有实现会导致崩溃  if ([self.delegate respondsToSelector:@selector(userLoginWithUsername:password:)]) {      // 调用代理对象的登录方法,代理对象去实现登录方法      [self.delegate userLoginWithUsername:self.username.text password:self.password.text];  }}代理方,实现具体的登录流程,委托方不需要知道实现细节。// 遵守登录协议@interface ViewController ()  @end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    LoginViewController *loginVC = [[LoginViewController alloc] init];    loginVC.delegate = self;    [self.navigationController pushViewController:loginVC animated:YES];}/** *  代理方实现具体登录细节 */- (void)userLoginWithUsername:(NSString *)username password:(NSString *)password {    NSLog(@"username : %@, password : %@", username, password);}


0 0