1.前言

自今年5月底正式转iOS之后,天天get新技能,很多技能在脑子里回旋不吐不快,所以,写点东西整理一下。先从协议代理开始。

2.协议方法的声明

@protocol EventMenuBarDelegate <NSObject>

- (void)delegateShouldDoWhenMenuButtonTapped:(UIButton *)button;

@end

以上代码意思是,利用@protocol 指令声明协议名EventMenuBarDelegate,并遵从NSObject协议,在协议中声明了一个方法

- (void)delegateShouldDoWhenMenuButtonTapped:(UIButton *)button,由于没有用@option 指令声明,所以服从该EventMenuBarDelegate的对象必须实现delegateShouldDoWhenMenuButtonTapped: 这个方法。

3.协议代理的认识

协议中声明的方法,其实就是C++等面向对象的编程语言的抽象方法,不需要具体实现过程,但是必须要声明方法接口,以用于继承该类的子类进行适配,这就是设计模式中的适配器模式。在Objective-C中,子类通过遵从协议和继承超类以达到C++的多继承的效果。我认为这样的好处就是,多态。

4.情景模拟与代码实现

委托代理其实就是某个对象需要完成某个方法所找的另外一个对象。比如,我是个懒人,我不喜欢洗衣服,我找洗衣助理帮我洗,此时,助理就是我洗衣服的委托代理,并且必须遵从洗衣协议并实现洗衣服的过程。在助理洗完之后,我再作为洗衣助理的委托代理表示感谢,向助理说谢谢并付钱。(有点绕,需要脑洞大开)如果用程序实现就可以像下面一样写。其实,这个情景中,代码模拟了两个委托代理,一个是洗衣服的协议代理,另外一个是整个业务逻辑的协议代理。

1)洗衣服的协议方法

#import <Foundation/Foundation.h>
#import "APPBLLDelegate.h" @protocol WashClothes <NSObject> - (void)washClothes:(int)num complete:(id<APPBLLDelegate>)delegate; @end

代码声明了洗衣服的协议,遵从该协议的所有对象必须完成一件事根据传入的衣服数量洗衣服,洗完之后代理我(代理)再做出响应的处理。

2)业务逻辑协议

@protocol APPBLLDelegate <NSObject>

- (void)didWashClothesSuccess:(BOOL)finished leftNum:(int)left;

- (void)didWashClotheFailed:(NSString *)errorMsg;

@end

业务逻辑的协议中,声明了两个方法,一个是洗衣成功后我需要做的,另一个是洗衣未成功我需要做的。其实,这里完全可以抽象成任何事件的协议方法,换个名字就成。比如,一次网络请求响应,一次数据库的读库写库。

而作为该业务逻辑的我(代理)而言,当洗衣助理把我当代理参数传入的时候,并不确定我的类型,仅作为一个id类型的对象指针传入,但是我必须遵循APPBLLDelegate协议,即

(id<APPBLLDelegate>)delegate

3)我(用户)的类代码实现

头文件

#import <Foundation/Foundation.h>
#import "WashClothes.h"
#import "APPBLLDelegate.h" @interface User : NSObject <APPBLLDelegate> @property int clothesNum;
@property (weak, nonatomic) id<WashClothes> delegate; - (void)askAssistantForWashingClothes; @end

我洗衣服的代理是助理,助理的类不一定是什么类,我不确定,所以用id类型来指代其类型(当然,如果确定的话就指定这个类名就好),但是助理必须遵循洗衣协议,即,

id<WashClothes> delegate

而我作为整个业务逻辑的代理,我也必须遵循业务逻辑的协议(脑洞再大点)。即,

 User : NSObject <APPBLLDelegate>

实现文件

#import "User.h"

@implementation User

- (void)askAssistantForWashingClothes {
[self.delegate washClothes:self.clothesNum complete:self];
} - (void)didWashClothesSuccess:(BOOL)finished leftNum:(int)left {
if (finished) {
NSLog(@"助理已洗完衣服,很感谢,支付洗衣费用");
} else {
NSLog(@"助理未能洗完衣服,剩余%d件", left);
}
} - (void)didWashClotheFailed:(NSString *)errorMsg {
if (errorMsg != nil) {
NSLog(@"报错:%@", errorMsg);
}
} @end

我不洗衣服,我请求助理洗衣服,那么助理必须遵循洗衣协议,并且实现其具体过程,但我不需要实现,我的任务仅是向代理发送洗衣消息。当我的助理洗完衣服之后,我作为业务逻辑的代理,我必须做出反应,比如我要说谢谢给钱,或者没洗完不给钱,再或者出现问题我要报错。

这里,业务逻辑可以抽象为一个网络请求,比如,网络状况良好,我请求成功,正确传参,正确返回。或者,网络状况良好,错误传参,错误返回。再或者,网络状况渣渣,就报错吧。。

4)洗衣助理要做的

头文件

#import <Foundation/Foundation.h>
#import "WashClothes.h" @interface Assistant : NSObject <WashClothes> @property int totalNum; - (instancetype)init; @end

洗衣助理必须遵循洗衣协议,即,

Assistant : NSObject <WashClothes>

实现洗衣方法,即,

- (void)washClothes:(int)num complete:(id<APPBLLDelegate>)delegate;

实现文件

#import "Assistant.h"

@implementation Assistant

- (instancetype)init {
self = [super init];
if (self) {
self.totalNum = ;
}
return self;
} - (void)washClothes:(int)num complete:(id<APPBLLDelegate>)delegate { int left = self.totalNum - num;
if (left > ) {
[delegate didWashClothesSuccess:YES leftNum:left];
} else {
[delegate didWashClothesSuccess:NO leftNum:abs(left)];
[delegate didWashClotheFailed:@"未能洗完衣服!"];
}
} @end

洗衣助理在初始化对象时,默认洗衣服最大数目是10件,并实现洗衣服的具体过程,洗完衣服之后给我(业务逻辑的代理)发送消息。也就是说,洗衣助理只需要洗衣服,不需要管洗完衣服做什么,剩下的将结果回传给我,让我来进行消息反馈。

5)程序单一入口

#import <Foundation/Foundation.h>
#import "User.h"
#import "Assistant.h" int main(int argc, const char * argv[]) {
@autoreleasepool { User *user = [[User alloc] init];
user.clothesNum = ; Assistant *assistance = [[Assistant alloc] init];
user.delegate = assistance; [user askAssistantForWashingClothes]; }
return ;
}

主程序创建了实例我,设置我的洗衣数量20,创建助理实例,设置我的洗衣委托代理为助理,最后向助理发送消息,助理执行洗衣服这个方法。

6)运行结果

2015-07-23 11:34:07.869 NYDelegateTest[1313:68830] 助理未能洗完衣服,剩余10

2015-07-23 11:34:07.870 NYDelegateTest[1313:68830] 报错:未能洗完衣服!

5.小结

1)Objective-C的协议可以实现适配器模式,通过继承和遵循协议,达到C++的多继承效果。通过该机制可以实现多子类的适配,使不同子类拥有各自独特的方法,匹配自身需求。

2)运用协议代理代码实现时,必须要设置实例的代理,比如,

user.delegate = assistance;

这一句必不可少,否则,代理是nil,发送消息就失效,方法不能执行,不会有任何输出。

3)这个模拟情景中,代码实现了两个协议代理。

一个是,我找助理作为我的洗衣代理。

另一个是,助理洗完衣服后,将处理结果回传给我(业务逻辑代理)。

4)在自学之初,我始终搞不清楚,table view的data source和delegate。现在才明白,其实两者都是协议代理,只不过名字不同罢了。data source的方法主要针对table view的一些UI数据源加载显示。而delegate更多的是对table view的一些操作作出响应(但是也有什么height之类的协议方法,我也是醉了,强迫症伤不起)。总之,如果单独创建table view 而不是用table view controller,data source和delegate都必须设置,且实现其协议方法。

5)文章如有理解错误,请留言交流,我会及时订正,感谢~

6)来上海之后,我两个月内成长了很多,学到很多,很感恩。我希望把我所学到明白的东西熟练应用,并能深入理解其原理,所以要学的很多很多。但是现在淡定多了。终生学习,快乐学习。谢谢帮助我的所有人 @不知霜舞哀伤udspj @280me @tinyfool ,我的美女leader @七了个六 。加油加油我可以做的更好!

iOS开发总结——协议代理的认识的更多相关文章

  1. iOS 开发之协议-代理传值

    刚开始做iOS开发的时候,对 protocol.delegate 的理解一直都是晕晕乎乎一知半解的状态,不知道两个UIViewController之间怎么进行传值. 面试过几个童鞋,问道怎么用 del ...

  2. iOS开发 中的代理实现

    iOS开发 中的代理实现 关于今天为什么要发这篇文字的原因:今天在和同事聊天的时候他跟我说项目中给他的block有时候不太能看的懂,让我尽量用代理写,好吧心累了,那就先从写个代理demo,防止以后他看 ...

  3. 浅谈iOS开发的协议(protocol)和代理(delegate)

    协议和代理对于一个新手来说确实不讨好理解,也有很多的iOS开发的老手对此是懂非懂的.网上的很多博文只是讲了怎么使用,并没有说的很明白.下面我谈一下我的理解. 1.你要先搞明白,协议和代理为什么会出现, ...

  4. 【转】iOS 开发之协议protocal-代理传值delegate

    原文网址:http://www.cnblogs.com/wzrong/p/3201938.html 刚开始做iOS开发的时候,对 protocol.delegate 的理解一直都是晕晕乎乎一知半解的状 ...

  5. Ios开发之协议protocol

    Protocol是ios开发中的一个难点也是一个重点,要想使用好,或者理解好它,可能需要时间的累积.今天我们就通过一个例子来简单的看一下,怎么样使用protocol. 我们今天用的例子就是模拟电脑插入 ...

  6. iOS开发HTTP协议相关知识总结

    HTTP原理 什么是URL URL中常见的几种协议 什么是HTTP协议 HTTP是做什么的 为什么要使用HTTP协议 HTPP协议的通信过程介绍 HTTP请求 HTTP响应 HTTP请求的选择 两种发 ...

  7. iOS开发之地图代理不起作用(提示vImage decode failed, falling back to CG path.)

    项目中用到了地图相关的东西,就把曾经的demo搬了出来,结果发现直接执行之前的demo没有问题,在xcode5下新建项目再把代码粘贴过来就会提示 May 5 11:36:21 infomedia-iP ...

  8. IOS开发之----协议与委托(Protocol and Delegate) 实例解析

    1 协议: 协议,类似于Java或C#语言中的接口,它限制了实现类必须拥有哪些方法. 它是对对象行为的定义,也是对功能的规范. 在写示例之前我给大家说下@required和@optional这两个关键 ...

  9. iOS开发 - Protocol协议及委托代理(Delegate)

    因为Object-C是不支持多继承的,所以很多时候都是用Protocol(协议)来代替.Protocol(协议)只能定义公用的一套接口,但不能提供具体的实现方法.也就是说,它只告诉你要做什么,但具体怎 ...

随机推荐

  1. KbmMW 4.50.00 测试版发布

    We are happy to announce the release of kbmMW v. 4.50.00 Beta Professional and Enterprise Edition wi ...

  2. 2018.07.20 atcoder Largest Smallest Cyclic Shift(贪心)

    传送门 题意:给你x个a,y个b,z个c,显然这些字符可以拼成若干字符串,然后求这些字符串中最小表示法表示出来的最大的那一个. 解法:贪心思想,用multiset维护现在拼成的字串,每次取一个最小的和 ...

  3. 一个 图片 滚动 飞入的css特效

    @keyframes bounceInLeft { from, 60%, 75%, 90%, to {animation-timing-function: cubic-bezier(0.215, 0. ...

  4. Linux命令:ps

    Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信 ...

  5. HDU 1197 Specialized Four-Digit Numbers (枚举+进制转化,简单)

    题意:让求从2992-9999中所有数字,满足10进制各位之和和12进制和16进制各位数字之和相等. 析:没啥可说的,只能枚举从2992-9999,每个进制都算一下. 代码如下: #include & ...

  6. Node开发文件上传系统及向七牛云存储和亚马逊AWS S3的文件上传

    背景起,有奏乐: 有伟人曰:学习技能的最好途径莫过于理论与实践相结合. 初学Node这货时,每每读教程必会Fall asleep. 当真要开发系统时,顿觉精神百倍,即便踩坑无数也不失斗志. 因为同团队 ...

  7. codeforces 261B Maxim and Restaurant(概率DP)

    B. Maxim and Restaurant time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  8. (原创)Hibernate persistentSet的remove()方法不起作用

    情景再现:hibernate 多对多  User对象(员工).Educate对象(培训课程),我想干的事情是想把第三方表格user_educate中的员工_培训课程中的一行信息删掉(删掉员工所选的一门 ...

  9. Sharepoint 安装部署Project Server

    #在SharePoint Central Administration-> Manage service applications中,点击New button,选择Project Service ...

  10. 一、配置etcd数据库

      etcd服务作为Kubernetes集群的主数据库,在安装Kubernetes各服务之前需要首先安装和启动. 1. 安装etcd yum -y install etcd 2. 修改etcd配置文件 ...