iOS开发总结——协议代理的认识
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开发总结——协议代理的认识的更多相关文章
- iOS 开发之协议-代理传值
刚开始做iOS开发的时候,对 protocol.delegate 的理解一直都是晕晕乎乎一知半解的状态,不知道两个UIViewController之间怎么进行传值. 面试过几个童鞋,问道怎么用 del ...
- iOS开发 中的代理实现
iOS开发 中的代理实现 关于今天为什么要发这篇文字的原因:今天在和同事聊天的时候他跟我说项目中给他的block有时候不太能看的懂,让我尽量用代理写,好吧心累了,那就先从写个代理demo,防止以后他看 ...
- 浅谈iOS开发的协议(protocol)和代理(delegate)
协议和代理对于一个新手来说确实不讨好理解,也有很多的iOS开发的老手对此是懂非懂的.网上的很多博文只是讲了怎么使用,并没有说的很明白.下面我谈一下我的理解. 1.你要先搞明白,协议和代理为什么会出现, ...
- 【转】iOS 开发之协议protocal-代理传值delegate
原文网址:http://www.cnblogs.com/wzrong/p/3201938.html 刚开始做iOS开发的时候,对 protocol.delegate 的理解一直都是晕晕乎乎一知半解的状 ...
- Ios开发之协议protocol
Protocol是ios开发中的一个难点也是一个重点,要想使用好,或者理解好它,可能需要时间的累积.今天我们就通过一个例子来简单的看一下,怎么样使用protocol. 我们今天用的例子就是模拟电脑插入 ...
- iOS开发HTTP协议相关知识总结
HTTP原理 什么是URL URL中常见的几种协议 什么是HTTP协议 HTTP是做什么的 为什么要使用HTTP协议 HTPP协议的通信过程介绍 HTTP请求 HTTP响应 HTTP请求的选择 两种发 ...
- iOS开发之地图代理不起作用(提示vImage decode failed, falling back to CG path.)
项目中用到了地图相关的东西,就把曾经的demo搬了出来,结果发现直接执行之前的demo没有问题,在xcode5下新建项目再把代码粘贴过来就会提示 May 5 11:36:21 infomedia-iP ...
- IOS开发之----协议与委托(Protocol and Delegate) 实例解析
1 协议: 协议,类似于Java或C#语言中的接口,它限制了实现类必须拥有哪些方法. 它是对对象行为的定义,也是对功能的规范. 在写示例之前我给大家说下@required和@optional这两个关键 ...
- iOS开发 - Protocol协议及委托代理(Delegate)
因为Object-C是不支持多继承的,所以很多时候都是用Protocol(协议)来代替.Protocol(协议)只能定义公用的一套接口,但不能提供具体的实现方法.也就是说,它只告诉你要做什么,但具体怎 ...
随机推荐
- KbmMW 4.50.00 测试版发布
We are happy to announce the release of kbmMW v. 4.50.00 Beta Professional and Enterprise Edition wi ...
- 2018.07.20 atcoder Largest Smallest Cyclic Shift(贪心)
传送门 题意:给你x个a,y个b,z个c,显然这些字符可以拼成若干字符串,然后求这些字符串中最小表示法表示出来的最大的那一个. 解法:贪心思想,用multiset维护现在拼成的字串,每次取一个最小的和 ...
- 一个 图片 滚动 飞入的css特效
@keyframes bounceInLeft { from, 60%, 75%, 90%, to {animation-timing-function: cubic-bezier(0.215, 0. ...
- Linux命令:ps
Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信 ...
- HDU 1197 Specialized Four-Digit Numbers (枚举+进制转化,简单)
题意:让求从2992-9999中所有数字,满足10进制各位之和和12进制和16进制各位数字之和相等. 析:没啥可说的,只能枚举从2992-9999,每个进制都算一下. 代码如下: #include & ...
- Node开发文件上传系统及向七牛云存储和亚马逊AWS S3的文件上传
背景起,有奏乐: 有伟人曰:学习技能的最好途径莫过于理论与实践相结合. 初学Node这货时,每每读教程必会Fall asleep. 当真要开发系统时,顿觉精神百倍,即便踩坑无数也不失斗志. 因为同团队 ...
- codeforces 261B Maxim and Restaurant(概率DP)
B. Maxim and Restaurant time limit per test 2 seconds memory limit per test 256 megabytes input stan ...
- (原创)Hibernate persistentSet的remove()方法不起作用
情景再现:hibernate 多对多 User对象(员工).Educate对象(培训课程),我想干的事情是想把第三方表格user_educate中的员工_培训课程中的一行信息删掉(删掉员工所选的一门 ...
- Sharepoint 安装部署Project Server
#在SharePoint Central Administration-> Manage service applications中,点击New button,选择Project Service ...
- 一、配置etcd数据库
etcd服务作为Kubernetes集群的主数据库,在安装Kubernetes各服务之前需要首先安装和启动. 1. 安装etcd yum -y install etcd 2. 修改etcd配置文件 ...