protocol(协议) 和 delegate(委托)也叫(代理)---辨析

复制代码

protocol和delegate完全不是一回事。协议(protocol),(名词)要求。就是使用了这个协议后就要按照这个协议来办事,协议要求实现的方法就一定要实现。委托(delegate),(动词)助手。顾名思义就是委托别人办事,就是当 一件事情发生后,自己不处理,让别人来处理。举个浅显的例子:我上班的工作主要内容包括 (1)写代码(2)写文档(3)测试程序(4)接电话(5)会见客户。(1)(2)我自己全权负责,但是后面(3)(4)(5)我不想或者不方便自己做,所以我想找个助手(delegate)帮我做这些事,于是我定了一个招聘要求(Protocol),里写明我的助手需要会做(3)(4)(5)这三件事。很快,我招到一个助手。即:我.delegate = 助手;
于是以后每当我遇到需要测试程序或者接电话的活,我就把他转交给助手(delegate)去处理,助手处理完后如果有处理结果(返回值)助手会告诉我,也许我会拿来用。如果不需要或者没有结果,我就接着做下面的事。。protocol和java里interface的概念类似,是Objective-C语法的一部分。
定义protocol如下
C代码  
@protocol ClassADelegate  - (void)methodA;  
- (void)methodB;  @end  那么就是定义了一组函数,这组函数放在一起叫作一个protocol,即 协议。函数是需要被实现的,所以如果对于class如下@interface ClassB <ClassADelegate> {  
}  
@end  就叫作ClassB conform(遵守)to protocol ClassADelegate,也就是说ClassB实现了这个协议,
也就是实现了这一组函数。有了上面这个头文件,我们就可以放心作调用
C代码  
ClassB *b = [[ClassB alloc] init];  
[b methodA];  
[b methodB];  而不用担心出现unrecognized selector sent to instance这种错误了。所以protocol就是一组函数定义,是从类声明中剥离出来的一组定义。
C代码  
id<ClassADelegate> b = ...; (把实现类对象 赋值给 遵守此协议的拥有者 b ) 
[b methodA];  这种用法也常见,b是一个id类型,它知道ClassADelegate这组函数的实现(即把实现类的对象赋值给b)。那么delegate是什么?其实和protocol没有关系。Delegate本身应该称为一种设计模式。
是把一个类自己需要做的一部分事情,让另一个类(也可以就是自己本身)来完成。
比如ClassC
C代码  
@interface ClassC {  id delegate;  
}  
@end  那么ClassC的实现(.m文件)里就可以用delegate这个变量了。
当然这里完全可以用其它名字而不是delegate。我们也可以这样写
C代码  
@interface ClassC {  ClassB *delegate;  
}  
@end  这样我们知道了delegate是一个ClassB,它就可以提供ClassB里的方法。
可以把一部分ClassC里的工作放在ClassB里去实现。
这样的写法看起来是不是有点奇怪?或者应该写成这样?
C代码  
@interface ClassC {  ClassB *classB;  
}  
@end  
…  delegate没有了…
所以说其实delegate只是一种模式,大家约定俗成,当把自己内部一部分实现暴露给另外一个类去做的时候,就叫实际做事的类为delegate(即助手)。为什么会需要把内部实现提出来给另一个类做呢?
最常见的目的就是为了在隐藏实现的前提下,提供一个自定义的机会。
比如Apple提供的iOS SDK里就有众多的delegate,比如最常用的UITableView,
我们没法知道Apple怎么重用UITableViewCell,怎么处理UITableView里Cell的增加、删减,因为我们没有源码。
但是我们可以通过实现Delegate的方法来控制一个UITableView的一些行为。(即把delegate方法实现)
UITableViewDataSource其实和delegate是一样一样的,只是由于意义不同换了个名字罢了。protocol在此扮演了什么角色呢?
protocol是一种语法,它提供了一个很方便的、实现delegate模式的机会。
比如写UITableView的时候,Apple这么干UITableView.m
C代码  
- (void)doSomething {  [self blahblah];  [self.delegate guruguru];  [self blahblah];  }  delegate是我们写的类,这个类如果可以被传给UITableView做为其delegate,那唯一要求,就是它实现了
- (void)guruguru;
这个方法。如果我们把这个方法定义在一个protocol里
C代码  
@protocol XXXProtocol  - (void)guruguru;  @end  就说明了,UITableView需要的delegate是一个conform to XXXProtocol的类。
这就正好是id<XXXProtocol>
表达的意思。
无论具体的类是什么,它还有其它什么方法,只要它conform to这个protocol,
就说明它可以被传给UITableView,作为它的delegate。那么Apple为了让我们知道这个protocol是delegate需要conform的protocol,
它就把XXXProtocol改成了UITableViewDelegate这样我们看到protocol的名字里有Delegate,就知道这个protocol里的函数是用来做自定义(Customization)的了。来源:http://haoxiang.org/2011/08/ios-delegate-and-protocol/Protocol 的其它问题1. 使用时为什么要加上 iOS.delegate = self物件名称.delegate = self,是在採用任何协定时 一定会看到的一行程式码,由于定义协定的类别并不需要实作协定内的方法,因为实作的部份是由採纳协定的类别来实作,但是它又必须要知道是由哪一个类别来实作,因此我们必须要把採纳协定类别的 instance 交给定义协定的类别,让它来使用。 另一方面并不是任何类别都可以将 instance 传给定义协定的类别来使用,其原因是,我们在定义此协定的类别里有宣告 delegate 变数时,有限定它必须要採纳此协定(id delegate)如果没有採用该协定就将 instance 传给定义该协定的类别,Xcode 同样会发出警告讯息。2. 为什么协定的生效位置不能写在建构式中协定的生效位置写在建构式中,并不会造成程式编译上的任何问题,因为这是属于逻辑上的错误,协定要正常生效它必须要知道实作它方法的类别的 instance,如果将生效的位置写在建构式中,在建立定义此协定的形态的变物件时,它的确会去触发此协定内的方法,但是由于并没有给它实作此协定方法类别的 instance,因此不会有任何效果产生,反之,如果一定要将生效的位置写在建构式中,那么在初始化时就必须要设定好 delegate 才行,也就是使用初始化的方法函式里还必须要带入一个参数物件好指定给 delegate。3. 在定义协定时同时也可以採用其他的协定如果在定义协定时同时又採用其他的协定,这会导致之后採纳此协定的类别,它必须同时实作出两个协定内的方法,同样地,你也可以利用此方式来扩充那些已经存在的协定。
C代码  
@protocol FurnaceDelegate <其它可能的协定名称>  4. 使用 @optional 提供选择性的实作@optional,如同它字面上的意义,在 @optional 之后的方法都可以是选择性的实作,在定义协定时使用此方法,可以让之后採纳此协定的类别不一定要完全实作出协定内的所有方法。
C代码  
@protocol FurnaceDelegate   
- (void)whenCalledDelegeteFunction;  @optional  
-(void)optionalDelegeteFunction;  @end  






delegate  protocol 是objective-c 语法的一部分 但他们两个却完全不是一回事。主要是我们经常在同一个文件里见到这两个东西

protocol(协议)我的理解就是定义这么一个东西。以后就按这里的规定来办事。

delegate(委托)  就是把事情委托给别人去办 

@required 就是必须去办的。比如UITableView  delegate里面的:

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

这个就是必须要实现的方法

@optional则是可做或不做。比如TUIableView  delegate 里面的:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

这个就是可要可不要

 

关于delegate  protocol 网上有一个例子讲的非常形象:

           我上班的工作主要内容包括 (1)写代码(2)写文档(3)测试程序(4)接电话(5)会见客户

(1)(2)我自己全权负责,但是后面(3)(4)(5)我不想或者不方便自己做,所以我想找个助手(delegate)帮我做这些事,于是我定了一个招聘要求(Protocol),里写明我的助手需要会做(3)(4)(5)这三件事。很快,我招到一个助手。

        即:我.delegate = 助手;

于是以后每当我遇到需要测试程序或者接电话的活,我就把他转交给助手(delegate)去处理,助手处理完后如果有处理结果(返回值)助手会告诉我,也许我会拿来用。如果不需要或者没有结果,我就接着做下面的事。。

下面实现一个简单的protocol 

在DelegateTest.h里实现protocol 

复制代码
//定义protocol 协议
#import <UIKit/UIKit.h>@protocol DelegateTestDelegate;
@interface DelegateTest : NSObject
{id<DelegateTestDelegate> delegate;
}
@property(nonatomic,assign)id<DelegateTestDelegate> delegate;
@property(nonatomic,assign)NSInteger nb;
-(void)printPublic;         //公开
@end//协议里的方法
@protocol DelegateTestDelegate<NSObject>-(void)print:(NSInteger)number;        //如果别的类也用到了这个protocol 那么就可以直接调用了。
-(void)print;
@end
复制代码

DelegateTest.m 文件

复制代码
#import "DelegateTest.h"@interface DelegateTest ()@end@implementation DelegateTest
@synthesize delegate;
@synthesize nb;//如果这个类是基于UIControllView的话。可以直接在ViewDidLoad里面调用。那么效果也是一样的  这里就相当于别的类里调用这个方法。起到激活的作用
-(void)printPublic
{[delegate print];[delegate print:nb];
}@end
复制代码

 

ViewController.h 文件

复制代码
#import <UIKit/UIKit.h>
#import "DelegateTest.h"
@interface ViewController : UIViewController<DelegateTestDelegate>  //这里的DelegateTestDelegate也就相当于UITableView里的UITableViewDelegate
{DelegateTest *delegateTest;
}@property (nonatomic, assign)DelegateTest *delegateTest;
@end
复制代码

ViewController.m 文件

复制代码
#import "ViewController.h"@interface ViewController ()@end@implementation ViewController
@synthesize delegateTest;- (void)viewDidLoad
{[super viewDidLoad];delegateTest = [[DelegateTest alloc]init];[delegateTest setDelegate:self];  //设置代理[delegateTest printPublic ];  //选择调用delegateTest 里的这个方法。然后就可以调用下面的print了。也就相当于把print给激活了// Do any additional setup after loading the view, typically from a nib.
}- (void)viewDidUnload
{[super viewDidUnload];// Release any retained subviews of the main view.
}//调用DelegateTest  protocol 里面的方法
-(void)print
{NSLog(@"qingjoin print succeed");
}
-(void)print:(NSInteger)number
{NSLog(@"%d",number);
}- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}@end
实现协议的步骤
1    //delegate,遵守协议

    //1, 定义协议拥有者:说明delegate对象是MaryProtocol类型的协议

    id <MaryProtocol>  delegate;//让拥有者(使用者) 遵守协议(先定义)

 

    //2,赋值协议拥有者:将当前对象 赋值 给协议拥有者

    delegate = curDelegate;

 













转载于:https://www.cnblogs.com/iOS-mt/p/4103218.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/472777.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

天池 在线编程 能否转换

文章目录1. 题目2. 解题1. 题目 给两个字符串 S 和 T, 判断 S 能不能通过删除一些字母(包括0个)变成 T. 样例1 输入: S "lintcode" 和 T "lint" 输出: true样例2 输入: S "lintcode" 和 T "ide" 输出: true样例3 输入: S "…

java 析构函数_C++与Java的区别(一)

一&#xff0c;前言网上经常看到编程语言之争&#xff0c;大伙儿皈依到不同门派&#xff0c;各自怀抱信仰&#xff0c;时不时还发生点儿“冲突”。这其中&#xff0c;C和Java的优劣&#xff0c;十多年前就常吵的火热。然而时代在进步&#xff0c;技术在发展&#xff0c;满街早已…

天池 在线编程 圣杯咒语

文章目录1. 题目2. 解题1. 题目 一段英文中同时出现大小写的字母中最大的那一个&#xff0c;现在给你一段英文&#xff0c;你能把这个字母找出来嘛&#xff1f; ps:一定存在答案 英文长度不会超过100000 样例 1&#xff1a; 输入&#xff1a;"aAbb" 输出&#xf…

crawler_java_数据平台结构

大数据生态架构 转载于:https://www.cnblogs.com/cphmvp/p/4105674.html

天池 在线编程 卡牌游戏(01背包)

文章目录1. 题目2. 解题1. 题目 你跟你的朋友在玩一个卡牌游戏&#xff0c;总共有 n 张牌。 每张牌的成本为 cost[i] 并且可以对对手造成 damage[i] 的伤害。 你总共有 totalMoney 元并且需要造成至少 totalDamage 的伤害才能获胜。 每张牌只能使用一次&#xff0c;判断你是否…

bean validation校验方法参数_Spring Boot 之使用 validation 验证参数

前言文本已收录至我的GitHub仓库&#xff0c;欢迎Star&#xff1a;https://github.com/bin392328206/six-finger种一棵树最好的时间是十年前&#xff0c;其次是现在我知道很多人不玩qq了,但是怀旧一下,欢迎加入六脉神剑Java菜鸟学习群&#xff0c;群聊号码&#xff1a;54968483…

LeetCode 891. 子序列宽度之和(数学)

文章目录1. 题目2. 解题1. 题目 给定一个整数数组 A &#xff0c;考虑 A 的所有非空子序列。 对于任意序列 S &#xff0c;设 S 的宽度是 S 的最大元素和最小元素的差。 返回 A 的所有子序列的宽度之和。 由于答案可能非常大&#xff0c;请返回答案模 10^97。 示例&#x…

hive建表语句_Hive数据如何同步到MaxCompute之实践讲解

摘要&#xff1a;本次分享主要介绍 Hive数据如何迁移到MaxCompute。MMA(MaxCompute Migration Assist)是一款MaxCompute数据迁移工具&#xff0c;本文将为大家介绍MMA工具的功能、技术架构和实现原理&#xff0c;再通过实际操作MMA&#xff0c;演示将Hive数据迁移到MaxCompute。…

Java 包及访问权限

文章目录1. package 包2. import3. JDK常见的包4. 访问权限5. jar 压缩1. package 包 作用&#xff1a;防止不同的人写的类的名称相同冲突了&#xff0c; package testPackage1.java; class testPg {public String talk(){return "talk()";} } class testAnother{p…

java phaser用法_第3章Phaser的使用-(java并发编程核心方法与框架)

3.1 Phaser的使用3.2 类Phaser的arriveAndAwaitAdvance()方法测试13.3 类Phaser的arriveAndAwaitAdvance()方法测试23.4 类Phaser的arriveAndDeregister()方法测试3.5 类Phaser的getPhase()和onAdvance()方法测试3.6 类Phaser的getRegisteredParties()方法和register()测试3.7 …

html选项卡_适用于Mac的最佳HTML文本编辑器,编码开发必备

一个好的文本编辑器对于想要建立网站或进行编码的任何人都是必不可少的。这对于习惯于面面俱到的环境的Mac开发人员而言更加明显。对于他们来说存在一系列不同的优质软件之选。今天小编将介绍几款Mac上好用的HTML文本编辑器&#xff0c;对于每一款文本编辑器&#xff0c;小编将…

java 判断请求为 ajax请求_Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,java 判断请求是不是ajax请求...

Java过滤器处理Ajax请求&#xff0c;Java拦截器处理Ajax请求&#xff0c;拦截器Ajax请求java 判断请求是不是ajax请求&#xff0c;Java判断是否为ajax请求>>>>>>>>>>>>>>>>>>>>>>>>>>>>&…

java set hashcode_Java学习笔记_180724_HashSet_hashCode()

HashSet泛型E必须重写hashCode方法&#xff0c;否则会导致add结果与预期不符如class NewClass{String s;public NewClass(String s){this.ss;}overridepublic int hashCode(){//此处返回字符串s的hashCode()return s.hashCode();}}NewClass n new NewClass("1");New…

LeetCode 1773. 统计匹配检索规则的物品数量

文章目录1. 题目2. 解题1. 题目 给你一个数组 items &#xff0c;其中 items[i] [typei, colori, namei] &#xff0c;描述第 i 件物品的类型、颜色以及名称。 另给你一条由两个字符串 ruleKey 和 ruleValue 表示的检索规则。 如果第 i 件物品能满足下述条件之一&#xff0…

LeetCode 1774. 最接近目标价格的甜点成本(DFS / 01背包)

文章目录1. 题目2. 解题1. 题目 你打算做甜点&#xff0c;现在需要购买配料。目前共有 n 种冰激凌基料和 m 种配料可供选购。而制作甜点需要遵循以下几条规则&#xff1a; 必须选择 一种 冰激凌基料。可以添加 一种或多种 配料&#xff0c;也可以不添加任何配料。每种类型的配…

线程间通信的几种方法_并发编程中的线程间通信

线程通信的目标是使线程间能够互相发送信号。另一方面&#xff0c;线程通信使线程能够等待其他线程的信号。线程通信常用的方式有:wait/notify 等待Volatile 内存共享CountDownLatch 并发工具使用 ReentrantLock 结合 Condition基本LockSupport实现线程间的阻塞和唤醒方式一&am…

【IOS】Target membership

Target membership是指XCode中&#xff0c;一个文件属于哪一个工程&#xff0c;在XCode左侧的工程面板中选中一个文件&#xff0c;在XCode右侧的属性面板中会显示其Target Membership&#xff0c;如下图。 当前的文件AppDelegate.m属于书谱这个Target。 Target Membership的一些…

LeetCode 1775. 通过最少操作次数使数组的和相等(贪心+双指针)

文章目录1. 题目2. 解题1. 题目 给你两个长度可能不等的整数数组 nums1 和 nums2 。 两个数组中的所有值都在 1 到 6 之间&#xff08;包含 1 和 6&#xff09;。 每次操作中&#xff0c;你可以选择 任意 数组中的任意一个整数&#xff0c;将它变成 1 到 6 之间 任意 的值&am…

LeetCode 1776. 车队 II(单调栈)

文章目录1. 题目2. 解题1. 题目 在一条单车道上有 n 辆车&#xff0c;它们朝着同样的方向行驶。 给你一个长度为 n 的数组 cars &#xff0c;其中 cars[i] [positioni, speedi] &#xff0c;它表示&#xff1a; positioni 是第 i 辆车和道路起点之间的距离&#xff08;单位&…

wpf计算字符大小占像素_LCD作为终端显示字符串的过程

LCD作为终端显示字符串的过程1.本文目的2.资源评估3.显示原理4.嵌入式上汉字处理5.结果验证与展示6.总结1.本文目的做嵌入式图形开发&#xff0c;我们往往都会利用到各种GUI进行交互设计&#xff0c;但是对于GUI的字符串处理与中文字库显示&#xff0c;也许并不会特别关注&…