protocol deviation,protocol compliance
它与协议委托完全不同。
协议(名词)要求。也就是在使用了这个协议之后,我们必须按照这个协议行事,协议要求的方法必须实现。
代表,(动词)助手。顾名思义,就是委托别人办事,就是有事的时候你不自己处理,让别人处理。
举个简单的例子:
我在工作中的主要工作内容包括(1)写代码(2)写文档(3)测试程序(4)接电话(5)会见客户。(1)(2)我对自己完全负责,但是后来(3)(4)(5)我不想或者不方便自己做,所以我想找一个助理(委托人)帮我做这些事情,于是我定了一个招聘要求(协议),上面写着我的助理需要能做这三件事(3)(4)(5)。很快,我招了一个助理。
即I .委托=助理;
所以以后每当我遇到需要测试程序或者接电话的工作,我都会交给我的助理(委托人)去处理。助手处理后,如果有处理结果(返回值),助手会告诉我,也许我会用。如果没有必要,没有结果,我会继续做下面的事情。
类似于java中的接口概念,协议是Objective-C语法的一部分。
按如下方式定义协议
c代码
@协议类注册
- (void)方法a;
- (void)方法b;
@end
然后定义一组功能,合起来称为协议,也就是协议。
函数需要实现,所以如果类如下
@ interface class b class a delegate {
}
@end
它被称为ClassB符合协议ClassADelegate,这意味着ClassB实现了这个协议。
也就是实现了这一套功能。
有了上面的头文件,我们就可以放心调用了。
c代码
class b * b=[[class b alloc]init];
[b方法a];
[b方法b];
不要担心将未识别的选择器发送到实例的错误。
所以协议是一组函数定义,一组从类声明中剥离出来的定义。
c代码
id class a证书b=.(将实现类对象分配给遵守此协议的所有者B)
[b方法a];
这种用法也很常见。B是一个id类型,它知道ClassADelegate的这组函数的实现(也就是把实现类的对象赋给B)。
那么什么是委托呢?其实和礼仪没什么关系。委托本身应该被称为设计模式。
是一个类需要做的一部分,让另一个类(或者自己)去做。
比如ClassC C。
c代码
@interface ClassC {
id代表;
}
@end
那么变量delegate就可以用在ClassC(的实现中。m文件)。
当然,您可以在这里使用其他名称来代替delegate。
我们也可以这样写。
c代码
@interface ClassC {
ClassB *委托;
}
@end
所以我们知道delegate是一个ClassB,它可以提供ClassB中的方法。
你可以把ClassC里的一些工作放到ClassB里来实现。
这种写法是不是看起来有点奇怪?还是应该这样写?
c代码
@interface ClassC {
ClassB * classB
}
@end
…
代理人走了.
所以实际上,委托只是一种模式,而且是常见的做法。当您将内部实现的一部分公开给另一个类来完成它时,您将调用实际执行事情的类delegate(即assistant)。
为什么需要提出另一个类的内部实现?
最常见的目的是在隐藏实现的前提下提供一个自定义机会。
比如苹果提供的iOS SDK中就有很多delegate,比如最常用的UITableView。
我们无法得知苹果如何复用UITableViewCell,如何处理UITableView中Cell的增删,因为我们没有源代码。
但是我们可以通过实现Delegate来控制UITableView的一些行为。(即实现委托方法)
UITableViewDataSource其实和delegate一样,只是由于含义不同而改了名字。
协议在这里扮演什么角色?
协议是一种语法,它为实现委托模式提供了便利的机会。
比如写UITableView的时候,苹果就是这么做的。
UITableView.m
c代码
-(无效)做某事{
【self blahblah】;
[self . delegate guruguru];
【self blahblah】;
}
Delegate是我们写的一个类。如果这个类可以作为它的委托传递给UITableView,那么唯一的要求就是实现它。
——(虚空)古鲁古鲁;
这个方法。
如果我们在协议中定义这个方法
c代码
@协议XXXProtocol
——(虚空)古鲁古鲁;
@end
也就是说UITableView需要的委托是一个符合XXXProtocol的类。
这恰好是
id XXXProtocol
表达的意思。
不管具体的类是什么,它有什么其他的方法,只要它符合这个协议,
这意味着它可以作为它的委托传递给UITableView。
为了让我们知道这个协议是代表需要遵守的协议,
它将XXXProtocol更改为UITableViewDelegate。
这样,当我们看到协议的名字有Delegate,就知道这个协议里的功能是用来定制的。
资料来源:http://haoxiang.org/2011/08/ios-delegate-and-protocol/
协议的其他问题
1.为什么用的时候要加iOS.delegate=self?
名字。delegate=self是采用任何协议时都必须看到的一行代码。由于定义协议的类不需要实现协议中的方法,所以实现部分由采用协议的类来实现,但它必须知道是哪个类实现的。因此,我们必须将采用该协议的类的实例提供给为其使用定义该协议的类。
另一方面,并不是所有的类都可以将实例传递给定义协议的类。原因是当我们在定义这个协议的类中声明delegate变量时,受限于它必须采用这个协议(id delegate)。如果我们把实例传递给定义这个协议的类,而没有采用这个协议,Xcode也会发出警告信息。
2.为什么施工中不能写协议的有效位置?
把协议的有效位置写在构造函数里,不会造成编程上的任何问题,因为这是逻辑错误。为了使协议正常生效,它必须知道实现其方法的类的实例。如果有效位置写在构造函数中,当创建定义协议形式的可变对象时,它确实会触发协议中的方法。但是它没有实现这个协议方法类的实例,所以不会有效果。相反,如果必须在构造函数中写入有效位置,那么就必须在初始化时设置delegate,即必须将一个参数对象带入初始化的方法函数中,才能赋给delegate。
3.在定义一个协议时,也可以采用其他协议。
如果在定义一个协议时同时采用了其他协议,这将导致后来采用本协议的类别。它必须同时实现两个协议中的方法。同样,您也可以使用这种方法来扩展那些现有的协议。
c代码
@ protocol furnace删除其他可能的协议名称
4.使用@optional提供可选的实现。
@optional,顾名思义,@optional之后的所有方法都可以有选择地实现。在定义协议时使用该方法可以使后来采用该协议的类不一定实现协议中的所有方法。
c代码
@礼宾部部长
-(void)whencalleddelegatefunction;
@可选
-(void)optionalDelegeteFunction;
@enddelegate协议是objective-c语法的一部分,但两者完全不同。主要是我们经常在同一个文件里看到这两个东西。
协议(Protocol)我的理解是定义这样一个东西。今后,我们将按照这里的规定行事。
委托就是把事情委托给别人。
@要求是必须要做的。例如,在UITableView委托中:
-(NSInteger)table view:(ui table view *)table view number of rowsin section:(NSInteger)section
这是必须实现的方法。
@optional是可选还是不可选。例如,在Tuiablewiewdelegate中:
-(void)表格视图:(UITableView *)表格视图didSelectRowAtIndexPath:(NSIndexPath *)索引路径
这个就是可要可不要
关于委托协议网上有一个例子讲的非常形象:
我上班的工作主要内容包括(1)写代码(2)写文档(3)测试程序(4)接电话(5)会见客户
(1)(2)我自己全权负责,但是后面(3)(4)(5)我不想或者不方便自己做,所以我想找个助手(代表)帮我做这些事,于是我定了一个招聘要求(协议),里写明我的助手需要会做(3)(4)(5)这三件事。很快,我招到一个助手。
即:我。代表=助手;
于是以后每当我遇到需要测试程序或者接电话的活,我就把他转交给助手(代表)去处理,助手处理完后如果有处理结果(返回值)助手会告诉我,也许我会拿来用。如果不需要或者没有结果,我就接着做下面的事。
下面实现一个简单的草案
在委派测试。h里实现草案
//定义草案协议
#导入UIKit/UIKit.h
@协议DelegateTestDelegate
@接口委托测试:ns对象
{
id DelegateTestDelegate委托;
}
@property(非原子,赋值)id DelegateTestDelegate委托;
@property(nonatomic,assign)NSInteger nb;
-(作废)打印公开;//公开
@end
//协议里的方法
@ protocol DelegateTestDelegate ns对象
-(void)print:(NSInteger)number;//如果别的类也用到了这个草案那么就可以直接调用了。
-(作废)打印;
@end
委托测试。m文件
#import DelegateTest.h
@interface DelegateTest()
@end
@实现委派测试
@合成代表;
@合成nb;
//如果这个类是基于UIControllView的话。可以直接在位置里面调用。那么效果也是一样的这里就相当于别的类里调用这个方法。起到激活的作用
-(无效)打印公共
{
[委托打印];
[委托打印:nb];
}
@end
ViewController.h文件
#导入UIKit/UIKit.h
#import DelegateTest.h
@界面视图控制器:uiview控制器DelegateTestDelegate//这里的委托测试委托也就相当于列表里的委托
{
委托测试*委托测试
}
@property (nonatomic,assign)委托测试*委托测试;
@end
ViewController.m文件
#导入ViewController.h
@interface ViewController()
@end
@实现视图控制器
@合成delegateTest
- (void)viewDidLoad
{
【超级viewDidLoad】;
委托测试=[[委托测试分配]初始化];
【委托测试集委托:self】;//设置代理
[委托测试打印公开];//选择调用委派测试里的这个方法。然后就可以调用下面的打印了。也就相当于把打印给激活了
//在加载视图之后进行任何额外的设置,通常是从笔尖.
}
-(无效)查看卸载
{
【超级viewDidUnload】;
//释放主视图的所有保留的子视图。
}
//调用委托测试协议里面的方法
-(无效)打印
{
NSLog(@qingjoin打印成功);
}
-(void)print:(NSInteger)编号
{
NSLog(@%d ,number);
}
-(BOOL)should autorotatepointerface orientation:(ui界面方向)界面方向
{
return (interfaceOrientation!=uiinterfaceinterationportraitupsidedown);
}
@end实现协议的步骤
1//委托,遵守协议//1, 定义协议拥有者:说明代表对象是玛丽协议类型的协议
id协议代理;//让拥有者(使用者)遵守协议(先定义)
//2,赋值协议拥有者:将当前对象赋值给协议拥有者
delegate=curDelegate
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。