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;

												

protocol(协议) 和 delegate(委托)也叫(代理)---辨析的更多相关文章

  1. C#中的委托 Delegate(委托 也叫代表,代表一类方法)

    1. 委托类似与 C或C++中的函数指针,但委托是 面向对象的,并且是类型安全的 详情可查看官方文档:https://msdn.microsoft.com/en-us/library/ms173172 ...

  2. 窥探Swift之协议(Protocol)和委托代理(Delegate)回调的使用

    协议与委托代理回调在之前的博客中也是经常提到和用到的在<Objective-C中的委托(代理)模式>和<iOS开发之窥探UICollectionViewController(四) - ...

  3. 【转】iOS开发-Protocol协议及委托代理(Delegate)传值

    原文网址:http://www.cnblogs.com/GarveyCalvin/p/4210828.html 前言:因为Object-C是不支持多继承的,所以很多时候都是用Protocol(协议)来 ...

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

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

  5. protocol(协议)

      可以用来声明一大堆方法(不能声明成员变量) 只要某个类遵守了这个协议,就相当于拥有这个协议中的所有方法声明 只要父类遵守了某个协议,就相当于子类也遵守了   //定义一个名叫MyProtocol的 ...

  6. Action<>和Func<> 委托【代理】

    C#中的Action<>和Func<> 其实他们两个都是委托[代理]的简写形式. 一.[action<>]指定那些只有输入参数,没有返回值的委托 Delegate的 ...

  7. ISO 基础之 (十三) protocol 协议

    一 简绍 protocol,简单来说就是一系列不属于任何类的方法列表,其中声明的方法可以被任何类实现.这种模式一般称为代理(delegation)模式.通过Protocol定义各种行为,在不同的场景采 ...

  8. OC语法10——@protocol协议,

    参考资料:博客 @protocol,协议: OC中protocol的含义和Java中接口的含义是一样的,它们的作用都是为了定义一组方法规范. 实现此协议的类里的方法,必须按照此协议里定义的方法规范来. ...

  9. SIP (Session Initiation Protocol) 协议

    Session Initiation Protocol 介绍 SIP是VoIP技术最常使用的协议,它是一种应用程序层协议,可与其他应用程序层协议配合使用,以控制Internet上的多媒体通信会话. V ...

  10. 【UE4 C++ 基础知识】<8> Delegate 委托

    概念 定义 UE4中的delegate(委托)常用于解耦不同对象之间的关联:委托的触发者不与监听者有直接关联,两者通过委托对象间接地建立联系. 监听者通过将响应函数绑定到委托上,使得委托触发时立即收到 ...

随机推荐

  1. disconf实践(一)

    公司目前的应用基本采用分布式部署,通过F5进行集群管理.分布式应用带来的好处是,随着流量的增加,可以快速扩展应用节点,分摊压力.分布式也会带来一定的挑战,譬如配置文件管理.如果某个配置要修改,那么所有 ...

  2. centos 6.5上部署jetty

    和tomcat是一样的,在部署容器之前,我们首先得有java环境 这里我们选择用rpm包的方式安装jdk 这里我们上传我之前下载好的jdk包 然后按照该文章http://blog.csdn.net/x ...

  3. array_column php 函数 自定义版本 php_version<5.5

    <?php if(!function_exists('array_column')) { /* * array_column() for PHP 5.4 and lower versions * ...

  4. Java实现平衡二叉树(AVLTree)的构建

    近期在学习数据结构上关于平衡二叉树的知识,看了严老师的思路,感觉用java写出递归的构建方式有点困难,由于当中的递归须要把引用传进去,所以感觉是要实现起来比較麻烦,所以就首先想到使用非递归的方式来实现 ...

  5. android 40 Io编程

    Io编程:内存卡和sd卡.字符串存入内存卡然后读出来. activity: package com.sxt.day06_06; import java.io.FileInputStream; impo ...

  6. SQLite的 SQL语法总结

    SQLite库可以解析大部分标准SQL语言.但它也省去了一些特性并且加入了一些自己的新特性.这篇文档就是试图描述那些SQLite支持/不支持的SQL语法的.查看关键字列表. 如下语法表格中,纯文本用蓝 ...

  7. Charles --- Mac 抓包工具

    安装 官方网站Charles 是一款收费软件,可以免费体验30天.网上有破解版. 使用 infoq 上有一篇很棒的教程:iOS开发工具——网络封包分析工具Charles 注意事项 这是我使用过程中遇到 ...

  8. JAVA异常的捕获与抛出原则

    在可能会出现exception的地方,要使用try-catch或者throws或者两者都要.我的判断依据是:如果对可能出现的exception不想被外部(方法的调用者)知道,就在方法内部try-cat ...

  9. Java基础知识强化之集合框架笔记18:List集合特有的ListIterator迭代器

    1. ListIterator(列表迭代器): ListIterator listIterator():List集合特有的迭代器 2. 代码示例: package cn.itcast_04; impo ...

  10. idea使用笔记

    常用快捷键 ctrl+shift+f12 编辑器全屏 win8下输入法不跟随 使用微软输入法即可 默认设置 之前创建maven工程 每次都要选择自己的版本,原来有个默认全局设置 创建maven模板工程 ...