最近看了些关于objective-c的正式协议和非正式协议的内容,发现还是有些混乱,可能是因为还不熟悉OC,对正式协议和非正式协议的使用还不是很熟练,所以想整理一下

非正式协议,是使用类别category来实现,非正式协议是NSObject的一个类别,这样任何类的对象都可以作为委托对象来使用,它可以列出对象能够执行的所有方法,这样用来实现委托, 我们可以使用选择器来判断该非正式协议中是否有这个方法。

正式协议,是一个命名的方法列表,与非正式协议相比不同的是,它要求显示的采用协议,采用协议的方法是在类的@interface声明中列出协议的名称,此时,实现协议的类应该遵守协议,承诺实现协议中的所有方法,否则编译器将会发出警告。

协议类似于C++的纯虚函数,协议只有声明,没有实现,用来在子类中实现,协议中的方法有两类属性,@required和@optional两种,@required属性的要求实现协议的类必须要实现这种方法,而@optional属性的方法则不要求,如果不确定协议是否被实现,可以使用respondsToSelector:@select()来判断。

下面是一个协议的声明和实现实例代码:

声明一个协议myprotocol

[cpp] view plaincopyprint?
  1. @protocol myprotocol <NSObject>
  2. @optional
  3. -(void)print:(int)value;
  4. //可选的方法
  5. @required
  6. -(int)printValue:(int)value1 andValue:(int)value2;
  7. //必须实现的
  8. @end

实现这个协议

mytest.h

[cpp] view plaincopyprint?
  1. #import <Foundation/Foundation.h>
  2. #import "myprotocol.h"
  3. //实现协议 myprotocol
  4. @interface mytest : NSObject<myprotocol>
  5. {
  6. }
  7. - (void)showInfo;
  8. @end

mytest.m

[cpp] view plaincopyprint?
  1. #import "mytest.h"
  2. @implementation mytest
  3. -(void)showInfo
  4. {
  5. NSLog(@"I am in showInfo");
  6. }
  7. //实现协议必须实现的
  8. -(int)printValue:(int)value1 andValue:(int)value2
  9. {
  10. NSLog(@"print value1 %d,value2 %d",value1,value2);
  11. return 0;
  12. }
  13. //实现可选的
  14. -(void)print:(int)value
  15. {
  16. NSLog(@"print value is %d",value);
  17. }
  18. @end

使用这个协议main.m

[cpp] view plaincopyprint?
  1. #import <Foundation/Foundation.h>
  2. #import "mytest.h"
  3. #import "myprotocol.h"
  4. int main (int argc, const char * argv[]) {
  5. NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  6. // insert code here...
  7. NSLog(@"Hello, World!");
  8. mytest *test=[[mytest alloc]init];
  9. [test showInfo];
  10. [test printValue:20 andValue:30];
  11. //print协议是可选的,所以在用之前一定要判断是否实现了,不然可能会出错,使用下面的方法
  12. //  [test print:20];
  13. SEL sel=@selector(print:);
  14. if([test respondsToSelector:sel]){
  15. [test print:11];
  16. }
  17. //用协议的方式实现
  18. id<myprotocol> protocol =[[[mytest alloc]init]autorelease];
  19. [protocol showInfo];
  20. [protocol printValue:200 andValue:300];
  21. if([protocol respondsToSelector:@selector(print:)]){
  22. [protocol print:111];
  23. }
  24. [test release];
  25. [pool drain];
  26. return 0;
  27. }

下面介绍使用正式协议来实现代理,或者叫委托,委托是一中推向,另一个类的对象会要求委托对象来执行它的某些操作。

下面的例子,有一个dog类,一个person类,每个person对象有一个狗,这条狗仅仅属于这个主人,狗会定时的通知主人,也就是调用person类的一些方法,这样在狗的类中就需要一个person的代理,要求主人调用一些方法,机制类似回调,如下:

dog.h

[cpp] view plaincopyprint?
  1. #import <Foundation/Foundation.h>
  2. @protocol dogBark;
  3. @interface Dog : NSObject {
  4. int _ID;
  5. NSTimer *timer;
  6. int barkCount;
  7. id <dogBark> delegate;        //存放狗的主人
  8. }
  9. @property int ID;
  10. @property (assign)id <dogBark> delegate;
  11. @end
  12. //定义一个人和狗通讯的协议 protocol
  13. @protocol dogBark<NSObject>
  14. -(void)bark:(Dog*)thisDog count:(int)count;
  15. @end

dog.m

[cpp] view plaincopyprint?
  1. #import "Dog.h"
  2. @implementation Dog
  3. @synthesize ID=_ID;
  4. @synthesize delegate;
  5. -(id)init
  6. {
  7. if(self = [super init]){
  8. //创建一个定时器user,每隔1.0s 就调用updateTimer:nil,并传递一个参数nil
  9. timer=[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateTimer:)  userInfo:nil repeats:YES];
  10. }
  11. return self;
  12. }
  13. -(void) updateTimer:(id)arg
  14. {
  15. barkCount++;
  16. NSLog(@"dog bar %d",barkCount);
  17. //调用主人delegate的bark:count方法,
  18. [delegate bark:self count:barkCount]; //回调机制
  19. }
  20. @end

person.h

[cpp] view plaincopyprint?
  1. #import <Foundation/Foundation.h>
  2. #import "Dog.h"
  3. @interface Person : NSObject<dogBark>
  4. {
  5. Dog *_dog;
  6. }
  7. @property (retain) Dog *dog;
  8. @end

person.m

[cpp] view plaincopyprint?
  1. #import "Person.h"
  2. @implementation Person
  3. @synthesize dog=_dog;
  4. -(void)setDog:(Dog*)aDog
  5. {
  6. if(_dog!=aDog){
  7. [_dog release];
  8. _dog=[aDog retain];
  9. // 通知dog的主人是当前人,self
  10. [_dog setDelegate:self];
  11. }
  12. }
  13. //当狗叫的时候,让狗来调用人的方法
  14. //这个方法来源于dogBark协议,Person类来实现
  15. -(void)bark:(Dog*)thisDog count:(int)count
  16. {
  17. NSLog(@"Person bark: this dog %d bark %d",[thisDog ID],count);
  18. }
  19. -(void)dealloc
  20. {
  21. self.dog=nil;
  22. [super dealloc];
  23. }
  24. @end

主函数mian.m

[cpp] view plaincopyprint?
  1. #import <Foundation/Foundation.h>
  2. #import "Dog.h"
  3. #import "Person.h"
  4. int main (int argc, const char * argv[]) {
  5. NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  6. // insert code here...
  7. NSLog(@"Hello, World!");
  8. Person *xiaoli = [[Person alloc]init];
  9. Dog *dog=[[Dog alloc]init];
  10. [dog setID:10];
  11. [xiaoli setDog:dog];
  12. [dog release];
  13. //程序循环在这里
  14. while (1) {
  15. [[NSRunLoop currentRunLoop]run];
  16. }
  17. [xiaoli release];
  18. [pool drain];
  19. return 0;
  20. }

使用非正式协议也可以实现委托,前面讲非正式协议是使用类别来实现的,

同样的是一个dog类,一个person类,person类有一条狗,再实现一个NSObject的类别,在类别中实现一个方法,通过dog对象来调用这个方法。

[cpp] view plaincopyprint?
  1. #import <Cocoa/Cocoa.h>
  2. @interface dog : NSObject {
  3. int _ID;
  4. }
  5. @property int ID;
  6. @end
[cpp] view plaincopyprint?
  1. #import "dog.h"
  2. @implementation dog
  3. @synthesize  ID=_ID;
  4. -(id)init
  5. {
  6. self=[super init];
  7. return self;
  8. }
  9. @end

person类

[cpp] view plaincopyprint?
  1. #import <Cocoa/Cocoa.h>
  2. #import "dog.h"
  3. @interface person : NSObject
  4. {
  5. dog *_mydog;
  6. }
  7. -(void)setDog:(dog*)aDog;
  8. -(id)mydog;
  9. -(void)callFun;
  10. @end
[cpp] view plaincopyprint?
  1. #import "person.h"
  2. #import "nsobject_categroy.h"
  3. @implementation person
  4. -(void)setDog:(dog*)aDog
  5. {
  6. if (_mydog!=aDog) {
  7. [_mydog release];
  8. _mydog=[aDog retain];
  9. }
  10. }
  11. -(id)mydog{
  12. return _mydog;
  13. }
  14. -(void)callFun{
  15. NSLog(@"call Fun!");
  16. [_mydog callFromNSObject];
  17. }
  18. -(void)dealloc{
  19. [self setDog:nil];
  20. [super dealloc];
  21. }
  22. @end

NSObject类别的实现,也就是非正式协议

[cpp] view plaincopyprint?
  1. #import <Cocoa/Cocoa.h>
  2. @interface  NSObject(myCategroy)
  3. -(void)callFromNSObject;
  4. @end
[cpp] view plaincopyprint?
  1. #import "nsobject_categroy.h"
  2. @implementation  NSObject(myCategroy)
  3. -(void)callFromNSObject
  4. {
  5. NSLog(@"I AM NSOBJECT FUNCTIONS");
  6. }
  7. @end

主函数:

[cpp] view plaincopyprint?
  1. #import <Foundation/Foundation.h>
  2. #import "person.h"
  3. #import "dog.h"
  4. int main (int argc, const char * argv[]) {
  5. NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  6. // insert code here...
  7. NSLog(@"Hello, World!");
  8. dog *d=[[dog alloc]init];
  9. [d setID:10];
  10. person *p=[[person alloc]init];
  11. [p setDog:d];
  12. [p callFun];
  13. [p release];
  14. [pool drain];
  15. return 0;
  16. }

这样就会调用callFromNSObject方法

类别主要有三个功能:

一、利用类别分散实现

二、利用类别创建前向引用,可以实现私有函数

三、非正式协议和委托类别

OC正式协议和非正式协议的区别相关推荐

  1. OC的正式协议和非正式协议

    最近看了些关于objective-c的正式协议和非正式协议的内容,发现还是有些混乱,可能是因为还不熟悉OC,对正式协议和非正式协议的使用还不是很熟练,所以想整理一下 非正式协议,是使用类别catego ...

  2. OC正式协议和非正式协议

    1.概念 非正式协议,非正式协议是NSObject类(包括它的子类)的类别,其所有的子类都含蓄地接受了这个协议.非正式协议中的方法是否实现都是可选的,因此在调用非正式协议中的方法之前,需要去检查对象类 ...

  3. OC中的非正式协议与正式协议的区别

    声明:以下内容转自:http://blog.csdn.net/wzzvictory/article/details/9295317# 这两个概念困扰我很久了,一直都很像搞清楚到非正式协议和正式协议有什 ...

  4. Object-C非正式协议与正式协议的区别

    Object-C非正式协议与正式协议的区别 Object-C非正式协议与正式协议的区别 - braddoris的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/br ...

  5. 非正式协议和正式协议的区别

    这两个概念困扰我很久了,一直都很像搞清楚到非正式协议和正式协议有什么区别和联系,下面结合网上的资料和自己的看法谈谈这个问题. 一.非正式协议 显然这个名词是相对于正式协议而言的.在解释非正式协议之前, ...

  6. 非正式协议与正式协议的区别

    正式和非正式协议 协议有两种类型-正式协议和非正式协议: 非正式协议是NSObject类的范畴类(范畴类是语言特征.通过它,您无需子类化就向某个类增加方法),这意味着几乎所有的对象都是非正式协议的采纳 ...

  7. Objective-C非正式协议与正式协议

    为什么80%的码农都做不了架构师?>>>    类别与类扩展的区别: ①类别中只能增加方法: ②是的,你没看错,类扩展不仅可以增加方法,还可以增加实例变量(或者合成属性),只是该实例 ...

  8. 2016 - 2- 2 非正式协议与正式协议

    在重温<OBJC编程基础>这本书时,对于非正式协议的感觉非常陌生,阅读了一篇王中周的博客,结合自己在书中阅读的内容,做一些总结. 一.非正式协议 显然这个名词是相对于正式协议而言的.在解释 ...

  9. Objective-C(八、正式协议Protocol,非正式协议informal protocol)——iOS开发基础

    结合之前的学习笔记以及参考<Objective-C编程全解(第三版)>,对Objective-C知识点进行梳理总结.知识点一直在变,只是作为参考,以苹果官方文档为准~ 八.正式协议和非正式 ...

最新文章

  1. Ubuntu 18.x 环境下mysql创建用户并更改用户权限
  2. SAP HANA里执行SQL语句的两种方式
  3. python运行程序的快捷键_在Python集成开发环境中,可使用快捷键()运行程序。...
  4. java从键盘上录入任何整数,输出该整数的阶乘
  5. mysql完整性约束命名_第5章--MySQL索引与完整性约束.ppt
  6. 「leetcode」617. 合并二叉树:【三种递归】【一种迭代】详解
  7. C#关键字=四六级核心词汇
  8. android studio for android learning (六)在布局中常使用的单位
  9. radius服务器连接无线网络,验证RADIUS服务器连接用测验AAA RADIUS命令
  10. Stata:图示交互效应-调节效应
  11. Django-Docker容器化部署:Django-Docker-MySQL-Nginx-Gunicorn云端部署
  12. BUUCTF中web方向题目记录(二)
  13. 一款对话网页游戏-对话部分
  14. SAP ABAP-获取屏幕字段数据
  15. 38个优秀博客站点推荐
  16. vue-public文件夹
  17. javascript 在页面显示xxxx年xx月xx日
  18. 【前端知识之JS】BOM的理解
  19. Game boy模拟器(8):中断
  20. 和包支付的钱哪里来_和包支付钱从哪里来的

热门文章

  1. ROS Couldn‘t find executable named xxx.py问题
  2. 大话设计模式——饕餮盛宴
  3. Spring Boot整合Freemarker
  4. MATLAB之拉氏变换
  5. Python+NumPy中的diag函数(简易理解)
  6. 京东出王炸,地下物流要来了!以后快递直接从管道送到家
  7. 中国科学技术大学计算机2020,中国科学技术大学2020年第七届计算机科学暑期夏令营报名通知...
  8. mmse评估量表_简易精神状态评价量表(MMSE)
  9. 如何提取pcap文件中的TCP流
  10. 2020年卫星行业研究报告