彻底理解Objective-C:协议(protocol),代理(delegate)

许多同学在第一次接触Objective-C里面的代理,协议,代理协议这些概念,很容易被搞晕.
再加上初次接触 Objective-C 类的property等写法看着比较陌生,更加剧了理解难度.
本文的目的就是,让你彻底理解协议,代理,以及他们的使用场景.
我将要用一个大家都熟悉的场景来讲解.

导演可以拍电影,调教演员,也可以进入到后期制作.导演也可以招聘"助理",帮他干后期制作的事情.

我们先写看协议.(protocol)协议=protocol


协议是什么? 协议就是一纸协议,听着好像废话,你可以从许多角度来看协议:

  • 协议是某种约定(或许多约定的组合)
  • 协议是双方要遵守的东西.
  • 协议是许多小项的组合.
  • 协议是双方的约定.
  • 协议有个协议名字
    那Objective-C里面呢, 协议就是”功能的集合”===>”方法的集合” ,也就是”能力清单”.

协议就是带名字的能力清单

我们先抛开Objective-C里面那些ViewController, DataSource, View那些概念,看上面说的具体的协议例子:

 # 影视行政助理协议(协议的名字) # 

功能列表:

  1:能寻找合适的胶片冲洗厂,进行胶片的冲洗(必须).

  2:后期音频合成,可以将录制好的音频合成到胶片里面(必须).

  3:需找海报制作商(必须).

  4:负责片场治安秩序(非必须)


所以,这个协议名字叫

”影视行政助理协议”

这是一纸清单.这个清单有4个项目(功能/方法),其中前3个是必须的.
协议有协议名字,有清单(方法列表,或者说功能列表)

协议就是”协议就是带名字的能力清单”.


下面再说代理().(delegate)

上面提到”协议是双方的约定”,否则单单只存在一份协议是没有意义的(但是没有错),我们来看看协议涉及到的双方.

  • 导演(Director):导演很忙,(实际上,那份协议就是导演自己编写的),因为他要把主要精力放到”艺术创作”上,把重要的琐事”代理”出去(这里的代理是动词),或者说把重要的琐事让”代理”去干(这里的代理是名词),为了便于理解,我们用名词这种方式.
    我们再看看实际情况下,影视圈的情况:
  • oldStreet:(老街)男,一个长期混迹影视圈的能人,行政能力很强,快50了,
    做事老派,不上网,没有微信,喜欢通过人脉干事,上面那4个活他都能干,尤其负责片场治安那个.
  • newSchool:(新校)女,刚刚毕业的电影学院学生,20出头,新潮人类,离开微信不能活那种,需要找工作.上面那个协议里面的事,她能干3个,负责片场治安秩序?还是算了吧.

现在,这两人都来应聘,都符合条件(就是说这两人都可以干协议里面规定必须能干的事情),在Objective-C里面,我们说”这两人都实现了这个协议”.

而导演这边呢,以前是孤家寡人,累的要死,现在有了助理了,对吧? ,以前导演可以这么自我介绍(导演的属性):

”XX导演,男,35岁,恐怖片导演,只做恐怖片,不是北京人,未婚”.

但是现在你要这么介绍了:

”XX导演,男,35岁,恐怖片导演,只做恐怖片,不是北京人,未婚,我的影视后期制助理是谁谁谁”.

如果导演太忙了,他可能还需要其他的人帮他干活,比如剧本医生,那就要这么介绍:

”XX导演,男,35岁,恐怖片导演,只做恐怖片,不是北京人,未婚,我的行政助理是谁谁谁,我的剧本医生是谁谁谁”.

这段意思是说,导演可以超过一个代理.我们把情况搞简单,先只给他一个代理(影视后期制作).
导演的影视后期制作是"某某某",这句话的复杂版本是:

某某某可以干"影视行政助理协议"这个协议里面规定的必须干的事情,导演的"导演的影视后期制作代理"被设置成"某某某",<br/>
导演可以安排助理干"影视行政助理协议"里面的任何事情了.

我们可以看到, 是 协议 将本来没有关系的两方(导演,某某某)联系了起来.
下面是filmAssistantProtocol.h 文件,就是协议文件.

@protocol 开头,
以@end结尾.
//filmAssistantProtocol.h
@protocol filmAssistantProtocol   //协议名字

@required
/*
 1:能寻找合适的胶片冲洗厂,进行胶片的冲洗(必须).
 2:后期音频合成,可以将录制好的音频合成到胶片里面(必须).
 3:需找海报制作商(必须).
 4:负责片场治安秩序(非必须)
 */

+(void) filmDeveloped;  //冲洗照片
+(void) audioProcess;   //音频合成
+(void) posterMake ;   //海报制造

@optional
-(void) siteSecurity; //现成安保

@end

我们可以很清楚的看到,协议(protocol)就是一个协议名字+功能列表(实际就是方法列表)

然后看看导演这里的写法(Director.h)

//
//  Director.h

#import <Foundation/Foundation.h>
#import "filmAssistantProtocol.h"

//#import "剧本医生协议.h"

@interface Director : NSObject

@property (strong, nonatomic) NSString   *directorName;  //定义导演的名字

//

/*定义一个后期制作的代理 backAssistant,这个代理遵守 filmAssistantProtocol 这个
协议,即:这个后期制作的代理 应该能干filmAssistantProtocol 这个协议里面定义的
功能集合
 
与通常我们见到的 
 @property(nonatomic, retain)  id <someProtocol>        delegate; 写法其实是一回事.
                                      |                   |
                                      |                   |
                                      V                   V
 @property(nonatomic, retain)  id<filmAssistantProtocol> backAssistant;

*/

@property(nonatomic, retain) id<filmAssistantProtocol> backAssistant;

/*我们目前只有一个代理,如果需要其他代理(比如剧本医生),将会是下面的写法*/

//@property(nonatomic, retain) id<剧本医生协议> 剧本代理人;

-(void) posterMake;  //印刷海报,导演自己也可以印刷海报
-(void) introMyself; // 导演自我介绍的方法.

@end

注意:与导演名字directorName并列的另外一个属性是backAssistant,
backAssistant/后期制做代理

再看看一个newSchool的情况:



//
//  newSchool.h
//  Film
//
//  Created by Alex on 4/9/16.
//  Copyright © 2016 Alex. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "filmAssistantProtocol.h"
@interface newSchool : NSObject<filmAssistantProtocol>  //实现了filmAssistantProtocol这个协议
@property (strong, nonatomic) NSString   *girlname;
//冲洗照片
-(void) filmDeveloped;
//音频合成
-(void) audioProcess;
//海报制造
-(void) posterMake;
@end

我们看到, filmAssistantProtocol 出现了两次,

  • Director.h ,可以理解成:[导演说,我要有个助理,能干后期制作那些事]
  • newSchool.h ,可以理解成:[一个毕业新手说,干后期制作那些事,我都能干]

最后的组合

 

//
//  ViewController.m
//

#import "ViewController.h"
#import "Director.h"
#import "newSchool.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSLog(@"程序开始了");
    Director* oneDirector = [[Director alloc] init]; //初始化一个导演
    
    oneDirector.directorName = @"PeterJ";    // PeterJ ,彼得杰克逊,指环王导演,这样让你们读代码好记.

    [oneDirector introMyself];   //导演介绍自己,虽然有"assistant"这个属性,但是还么有指定具体人.
    
    [oneDirector posterMake];   //导演自己也可以posterMake,因为他有这个方法.
    
    newSchool* oneGirl = [[newSchool alloc] init];  //定义一个新派的女学生,因为这个newSchool实现了那个协议,所以她就有那些能力.
    oneGirl.girlname = @"小花蝴蝶";
    
    //设置代理,把导演的后期制作代理设置成这个'小花蝴蝶',以后印海报那些事就交给小花蝴蝶干.
    /*
     我们在代码里面常见的那种写法
      XXX.delegate=self;
    或  
     
     XXX.delegate=yyy;
     与下面其实是一个意思.
     
     */
    
    oneDirector.backAssistant = oneGirl;    //把这个女孩指定为导演的那些干杂事的代理.
    
    [oneDirector introMyself];          //导演再次描述自己,backAssistant已经有人了.
    
    [oneDirector.backAssistant posterMake]; //导演可以让自己的backAssistant 去弄海报这事了.
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

运行时候注意看Xcode的日志. 希望对你有帮助.


协议/代理的使用场景

从上面的描述可以看到, 协议和代理基本是一起使用的,是为了降低复杂度,
即:把某些功能"聚合"到一个协议里面去, 然后请代理干活.
你基本可以理解成一种设计模式,或者是一种架构方法.

这种模式的常用做法,

  • 定义某一类的功能集合(协议),然后
  • 新的类实现协议里面的功能
  • 其他类,指定自己的代理是别人,让别人干功能集合里面的某些事情

示范工程在:
https://github.com/tangyongjin/Film

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容