在现实生活中我们存在各种各样的协议,但是都有一个共同点,就是拟定的协议,就要遵守,不遵守就是违约。在OC中也有协议这一个概念而且和我们现实生活中的协议的特点是类似的。有时我们自己想做什么事,但是现在没这个能力自己去做,亲力亲为,我们就需要找代理来帮我们做了。那么在OC中也有代理这个概念。下面就简单的说说OC中的协议和代理。
一、协议
在《【IOS开发之Objective-C】对象的交互》中实现了一种对象的交互的方式。在OC中还有其他方式,比如说协议,在OC中用协议来规范接口,是实现对象之间的交互的一种机制。类似于JAVA中的接口。还可以模拟多继承。
协议的实现
第一步:使用Xcode新建一个工程;
怎么新建一个工程《【IOS开发之Objective-C】新建第一个工程-HelloWorld》。
第二步:新建一个OC文件;
在这个工程里面 New File-----> Objective-C File -----> 填写文件名 – > 在File Type 里面选择“Protocol” 最后点击Next。
第三步:“拟定”协议;
假设我和某人签订和一个协议,协议里面需要我执行一个动作:每天练习一小时OC编程;那么这条协议内容就是: - (void)aDayCodeOneHour;这只是一个协议条款,协议自己本身事没有能力遵守协议或是实现协议。
#import <Foundation/Foundation.h> @protocol MyProtocol <NSObject> - (void)aDayCodeOneHour; @required //缺省属性,必须要实现 - (void)show; //show 是必须要实现 @property (nonatomic,assign) int a; @optional // 可选实现 - (void)show1; //show1 是可实现也可不实现 @end
第四步:遵守协议;
新建一个Person的类,在这个类.m文件里面来实现这个方法。在实现之前需要先表明你为什么实现这个方法。那么我们就需要在Person这个类里面表明我是遵守这个协议。我们就需要在类的.h文件里面表明我是遵守这个协议的。
#import <Foundation/Foundation.h> #import "MyProtocol.h" @interface Person : NSObject <MyProtocol> @property (nonatomic,assign) int a; @end
这里我们要做两件事,第一是包好协议这个头文件,第二就是@interface Person : NSObject <MyProtocol>。接下来就是协议的实现了。在Person.m这个文件中我们简单的实现一下:
#import "Person.h" @implementation Person - (void)aDayCodeOneHour{ NSLog(@"我的协议内容是“每天练习一小时OC编程”"); } - (void)show{ NSLog(@"这是一个协议的例子。"); } @end
第五步:主函数中演示
#import <Foundation/Foundation.h> #import "Person.h" int main(int argc, const char * argv[]) { @autoreleasepool { Person * ps = [[Person alloc] init]; [ps aDayCodeOneHour]; //默认的也是必须要实现的 [ps show]; //调用@required 修饰的一个方法 ps.a = 10; //给a赋值 NSLog(@"%d",ps.a); //取a的值打印出来 id<MyProtocol>obj = ps; //使用di的方法表明obj就是一个对象ps [obj show];//obj 也调用show 这个方法 } return 0; }
我们在协议MyProtocol 里面还有几句是没有说明的:
@required
//缺省属性,必须要实现
- (void)show;
//show 是必须要实现
@property (nonatomic,assign)int a;
@optional
// 可选实现
- (void)show1;
//show1 是可实现也可不实现 l例子中没实现
@required 缺省属性,被他修饰的方法是必须要实现的;
@optional 可选属性,被他修饰的方法可以不实现
在协议中我们不能声明变量,但是我们可以使用属性的方法:
@property (nonatomic,assign)int a;
在协议遵守方中要实现这个,也是在.h文件中粘贴一些这条语句,系统自动会给我们生产set和get方法。
主函数就比较简单了,但是需要学习这一句:
id<MyProtocol>obj = ps;//使用id的方法表明obj就是一个对象ps的副本
[obj show];//obj也调用show
这个方法
id的这一句,这里使用一个id类遵守MyProtocol协议的对象obj,让这个对象和对象ps指向的是同一块内存区域。
怎么模拟多继承呢?
其实也不难,我们可以这么实现<协议1,协议2 > 。其实在系统库里面也有很多这样的写法。这里我就不写了。
二、代理模式
什么是代理?
代理模式是实现两个对象之间的交互的一种机制。在代理模式中涉及到两个对象,一个是主动方一个是被动方。
主动方:拟定协议,创建一个携带协议的 id 指针(指向某个具体的代理);
被动方:遵守协议,实现协议的方法。
生活情境
现在什么送外卖的很是多,每天路上都有很多发单的。我们不想取买饭,就可以叫外卖。我们可以指定哪一家吃什么?我们也不能说拿了外卖就不给钱吧,我们还需要给商家付款。这里涉及到四个问题。我买哪一家的饭?我买什么饭?我要给卖家付款。卖家需要得到他的饭款。情境拆解后就是这么几个步骤了。
①.买家的需求:我要吃饭,吃哪家的什么饭呢?
②.买家选店铺和吃什么;
③.卖家给买家送饭;
④.买家给卖家付款;
⑤.卖家得到他的饭款。
代理的实现
有了这些步骤下面实现起来就不难了。
#import <Foundation/Foundation.h> //在主动方拟定协议 @protocol BuyFood <NSObject> - (void)sendFood;//卖家送餐 - (void)getMoney:(int)money;//卖家得到饭钱 @end @interface Person : NSObject - (void)wantToEat:(NSString *)food;//买家想吃饭 什么饭 - (void)give:(int)money;//卖家给卖家多少钱 //声明一个带有协议指针的属性 @property (nonatomic,assign) id<BuyFood>delegate; @end
#import "Person.h" @implementation Person - (void)wantToEat:(NSString *)food{ //选好吃什么 NSLog(@"顾客:我想吃 %@",food); [self.delegate sendFood]; } - (void)give:(int)money{ //买家付款 //注意这里的 self.delegate [self.delegate getMoney:money]; //付款给给我送餐的卖家 } @end
#import <Foundation/Foundation.h> #import "Person.h" @interface Rooom : NSObject <BuyFood> - (void)show; - (void)wantToGetMyMoney; @end
#import "Rooom.h" @implementation Rooom { int _money; } - (void)sendFood{ //卖家送餐 NSLog(@"店家:好的我马上给您派送"); } - (void)getMoney:(int)money{ _money = money; //卖家得到饭钱就放进他自己的口袋了 } - (void)wantToGetMyMoney{ //卖家想得到饭钱就需要买家付款 买家付款给对应的卖家 //这里就是代理的回调 Person * p1 = [[Person alloc] init]; p1.delegate = self; //注意这里的self 谁调用这个方法self就是谁 [p1 give:15]; //give是主动方的方法 买家付款15元 } - (void)show{ NSLog(@"店家:我得到了我的money:%d",_money); } @end #import <Foundation/Foundation.h> #import "Person.h" #import "Rooom.h" int main(int argc, const char * argv[]) { @autoreleasepool { Person * per = [[Person alloc] init]; Rooom * roo = [[Rooom alloc] init]; [per wantToEat:@"鱼香肉丝饭"]; //我想吃鱼香肉丝饭 per.delegate = roo; //指定代理 设置代理 选店铺 [roo sendFood]; //卖家送餐 [roo wantToGetMyMoney]; //买家付款 卖家得到饭钱 [roo show]; //高兴的卖家 说我得到了多少钱 } return 0;
输出:
2015-08-03 21:41:15.656 3.代理模式[3528:303] 顾客:我想吃 鱼香肉丝饭 2015-08-03 21:41:15.673 3.代理模式[3528:303] 店家:好的我马上给您派送 2015-08-03 21:41:15.674 3.代理模式[3528:303] 店家:我得到了我的money:15
Program ended with exitcode: 0
以上就这这个情景模式的全部代码。里面有协议,有代理也有代理的回调。每一步是做什么的上面有分析,代码中也有注释。
我们再来分析:
①.买家的需求:我要吃饭,吃哪家的什么饭呢?
②.买家选店铺和吃什么 // 买家选店铺指定代理
③.卖家给买家送饭; // 选定店铺后卖家需要做的 协议
④.买家给卖家付款; // 给代理传值正向传值 买家给卖家付款
⑤.卖家得到他的饭款。 // 代理的回调卖家需要从买家那里得到饭钱
代理的回调
代理的回调:调用某个功能模块,这个功能模块返回一些数据,但是功能不知道具体返回给哪个对象,这个时候,我们可以通过协议规范接收者接收数据方法,这个过程就是回调。
代理的回调也在上面的情境里面可,代码上面也有。
三、总结
通过上面的具体实例,我们要知道什么是协议?什么是代理?协议和代理之间的联系。怎么去实现一个简单的协议,或是说协议的基本格式是什么?代理的基本格式是什么?代理怎么回调?
当然上面这些举例和代码是不足以使我加深对协议和代理的理解的,还需要我在工作和学习中多总结,理论联系实际。
版权声明:本文为博主原创文章,未经博主允许不得转载。