許多同學(xué)在第一次接觸Objective-C里面的代理,協(xié)議,代理協(xié)議這些概念,很容易被搞暈.
再加上初次接觸 Objective-C 類的property等寫法看著比較陌生,更加劇了理解難度.
本文的目的就是,讓你徹底理解協(xié)議,代理,以及他們的使用場景.
我將要用一個大家都熟悉的場景來講解.
導(dǎo)演可以拍電影,調(diào)教演員,也可以進(jìn)入到后期制作.導(dǎo)演也可以招聘"助理",幫他干后期制作的事情.
我們先寫看協(xié)議.(protocol)協(xié)議=protocol
協(xié)議是什么? 協(xié)議就是一紙協(xié)議,聽著好像廢話,你可以從許多角度來看協(xié)議:
- 協(xié)議是某種約定(或許多約定的組合)
- 協(xié)議是雙方要遵守的東西.
- 協(xié)議是許多小項的組合.
- 協(xié)議是雙方的約定.
- 協(xié)議有個協(xié)議名字
那Objective-C里面呢, 協(xié)議就是”功能的集合”===>”方法的集合” ,也就是”能力清單”.
協(xié)議就是帶名字的能力清單
我們先拋開Objective-C里面那些ViewController, DataSource, View那些概念,看上面說的具體的協(xié)議例子:
# 影視行政助理協(xié)議(協(xié)議的名字) #
功能列表:
1:能尋找合適的膠片沖洗廠,進(jìn)行膠片的沖洗(必須).
2:后期音頻合成,可以將錄制好的音頻合成到膠片里面(必須).
3:需找海報制作商(必須).
4:負(fù)責(zé)片場治安秩序(非必須)
所以,這個協(xié)議名字叫
”影視行政助理協(xié)議”
這是一紙清單.這個清單有4個項目(功能/方法),其中前3個是必須的.
協(xié)議有協(xié)議名字,有清單(方法列表,或者說功能列表)
協(xié)議就是”協(xié)議就是帶名字的能力清單”.
下面再說代理(人).(delegate)
上面提到”協(xié)議是雙方的約定”,否則單單只存在一份協(xié)議是沒有意義的(但是沒有錯),我們來看看協(xié)議涉及到的雙方.
- 導(dǎo)演(Director):導(dǎo)演很忙,(實際上,那份協(xié)議就是導(dǎo)演自己編寫的),因為他要把主要精力放到”藝術(shù)創(chuàng)作”上,把重要的瑣事”代理”出去(這里的代理是動詞),或者說把重要的瑣事讓”代理”去干(這里的代理是名詞),為了便于理解,我們用名詞這種方式.
我們再看看實際情況下,影視圈的情況: - oldStreet:(老街)男,一個長期混跡影視圈的能人,行政能力很強(qiáng),快50了,
做事老派,不上網(wǎng),沒有微信,喜歡通過人脈干事,上面那4個活他都能干,尤其負(fù)責(zé)片場治安那個. - newSchool:(新校)女,剛剛畢業(yè)的電影學(xué)院學(xué)生,20出頭,新潮人類,離開微信不能活那種,需要找工作.上面那個協(xié)議里面的事,她能干3個,負(fù)責(zé)片場治安秩序?還是算了吧.
現(xiàn)在,這兩人都來應(yīng)聘,都符合條件(就是說這兩人都可以干協(xié)議里面規(guī)定必須能干的事情),在Objective-C里面,我們說”這兩人都實現(xiàn)了這個協(xié)議”.
而導(dǎo)演這邊呢,以前是孤家寡人,累的要死,現(xiàn)在有了助理了,對吧? ,以前導(dǎo)演可以這么自我介紹(導(dǎo)演的屬性):
”XX導(dǎo)演,男,35歲,恐怖片導(dǎo)演,只做恐怖片,不是北京人,未婚”.
但是現(xiàn)在你要這么介紹了:
”XX導(dǎo)演,男,35歲,恐怖片導(dǎo)演,只做恐怖片,不是北京人,未婚,我的影視后期制助理是誰誰誰”.
如果導(dǎo)演太忙了,他可能還需要其他的人幫他干活,比如劇本醫(yī)生,那就要這么介紹:
”XX導(dǎo)演,男,35歲,恐怖片導(dǎo)演,只做恐怖片,不是北京人,未婚,我的行政助理是誰誰誰,我的劇本醫(yī)生是誰誰誰”.
這段意思是說,導(dǎo)演可以超過一個代理.我們把情況搞簡單,先只給他一個代理(影視后期制作).
導(dǎo)演的影視后期制作是"某某某",這句話的復(fù)雜版本是:
某某某可以干"影視行政助理協(xié)議"這個協(xié)議里面規(guī)定的必須干的事情,導(dǎo)演的"導(dǎo)演的影視后期制作代理"被設(shè)置成"某某某",<br/>
導(dǎo)演可以安排助理干"影視行政助理協(xié)議"里面的任何事情了.
我們可以看到, 是 協(xié)議 將本來沒有關(guān)系的兩方(導(dǎo)演,某某某)聯(lián)系了起來.
下面是filmAssistantProtocol.h 文件,就是協(xié)議文件.
以
@protocol 開頭,
以@end結(jié)尾.
//filmAssistantProtocol.h
@protocol filmAssistantProtocol //協(xié)議名字
@required
/*
1:能尋找合適的膠片沖洗廠,進(jìn)行膠片的沖洗(必須).
2:后期音頻合成,可以將錄制好的音頻合成到膠片里面(必須).
3:需找海報制作商(必須).
4:負(fù)責(zé)片場治安秩序(非必須)
*/
+(void) filmDeveloped; //沖洗照片
+(void) audioProcess; //音頻合成
+(void) posterMake ; //海報制造
@optional
-(void) siteSecurity; //現(xiàn)成安保
@end
我們可以很清楚的看到,協(xié)議(protocol)就是一個協(xié)議名字+功能列表(實際就是方法列表)
然后看看導(dǎo)演這里的寫法(Director.h)
//
// Director.h
#import <Foundation/Foundation.h>
#import "filmAssistantProtocol.h"
//#import "劇本醫(yī)生協(xié)議.h"
@interface Director : NSObject
@property (strong, nonatomic) NSString *directorName; //定義導(dǎo)演的名字
//
/*定義一個后期制作的代理 backAssistant,這個代理遵守 filmAssistantProtocol 這個
協(xié)議,即:這個后期制作的代理 應(yīng)該能干filmAssistantProtocol 這個協(xié)議里面定義的
功能集合
與通常我們見到的
@property(nonatomic, retain) id <someProtocol> delegate; 寫法其實是一回事.
| |
| |
V V
@property(nonatomic, retain) id<filmAssistantProtocol> backAssistant;
*/
@property(nonatomic, retain) id<filmAssistantProtocol> backAssistant;
/*我們目前只有一個代理,如果需要其他代理(比如劇本醫(yī)生),將會是下面的寫法*/
//@property(nonatomic, retain) id<劇本醫(yī)生協(xié)議> 劇本代理人;
-(void) posterMake; //印刷海報,導(dǎo)演自己也可以印刷海報
-(void) introMyself; // 導(dǎo)演自我介紹的方法.
@end
注意:與導(dǎo)演名字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> //實現(xiàn)了filmAssistantProtocol這個協(xié)議
@property (strong, nonatomic) NSString *girlname;
//沖洗照片
-(void) filmDeveloped;
//音頻合成
-(void) audioProcess;
//海報制造
-(void) posterMake;
@end
我們看到, filmAssistantProtocol 出現(xiàn)了兩次,
- Director.h ,可以理解成:[導(dǎo)演說,我要有個助理,能干后期制作那些事]
- newSchool.h ,可以理解成:[一個畢業(yè)新手說,干后期制作那些事,我都能干]
最后的組合
//
// 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]; //初始化一個導(dǎo)演
oneDirector.directorName = @"PeterJ"; // PeterJ ,彼得杰克遜,指環(huán)王導(dǎo)演,這樣讓你們讀代碼好記.
[oneDirector introMyself]; //導(dǎo)演介紹自己,雖然有"assistant"這個屬性,但是還么有指定具體人.
[oneDirector posterMake]; //導(dǎo)演自己也可以posterMake,因為他有這個方法.
newSchool* oneGirl = [[newSchool alloc] init]; //定義一個新派的女學(xué)生,因為這個newSchool實現(xiàn)了那個協(xié)議,所以她就有那些能力.
oneGirl.girlname = @"小花蝴蝶";
//設(shè)置代理,把導(dǎo)演的后期制作代理設(shè)置成這個'小花蝴蝶',以后印海報那些事就交給小花蝴蝶干.
/*
我們在代碼里面常見的那種寫法
XXX.delegate=self;
或
XXX.delegate=yyy;
與下面其實是一個意思.
*/
oneDirector.backAssistant = oneGirl; //把這個女孩指定為導(dǎo)演的那些干雜事的代理.
[oneDirector introMyself]; //導(dǎo)演再次描述自己,backAssistant已經(jīng)有人了.
[oneDirector.backAssistant posterMake]; //導(dǎo)演可以讓自己的backAssistant 去弄海報這事了.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
運(yùn)行時候注意看Xcode的日志. 希望對你有幫助.
協(xié)議/代理的使用場景
從上面的描述可以看到, 協(xié)議和代理基本是一起使用的,是為了降低復(fù)雜度,
即:把某些功能"聚合"到一個協(xié)議里面去, 然后請代理干活.
你基本可以理解成一種設(shè)計模式,或者是一種架構(gòu)方法.
這種模式的常用做法,
- 定義某一類的功能集合(協(xié)議),然后
- 新的類實現(xiàn)協(xié)議里面的功能
- 其他類,指定自己的代理是別人,讓別人干功能集合里面的某些事情