OC正式协议和非正式协议
  JDh7sMsPQI0Y 2023年11月02日 44 0


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

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

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

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

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

声明一个协议myprotocol



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


实现这个协议

mytest.h



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

mytest.m



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


使用这个协议main.m

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


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

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

dog.h



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


dog.m



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



person.h



1. #import <Foundation/Foundation.h>  
2. #import "Dog.h"  
3.   
4. @interface Person : NSObject<dogBark>  
5. {  
6.   
7.     Dog *_dog;  
8. }  
9.   
10. @property (retain) Dog *dog;  
11. @end


person.m


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

主函数mian.m



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



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

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




      1. #import <Cocoa/Cocoa.h>  
      2.   
      3. @interface dog : NSObject {  
      4. int _ID;  
      5.     }  
      6. @property int ID;  
      7.   
      8. @end




      1. #import "dog.h"  
      2.   
      3. @implementation dog  
      4. @synthesize  ID=_ID;  
      5. -(id)init  
      6. {  
      7.     self=[super init];  
      8. return self;  
      9. }  
      10.   
      11. @end


      person类




        1. #import <Cocoa/Cocoa.h>  
        2. #import "dog.h"  
        3.   
        4. @interface person : NSObject   
        5. {  
        6.     dog *_mydog;  
        7. }  
        8.   
        9. -(void)setDog:(dog*)aDog;  
        10. -(id)mydog;  
        11. -(void)callFun;  
        12. @end


        1. #import "person.h"  
        2. #import "nsobject_categroy.h"  
        3.   
        4. @implementation person  
        5.   
        6. -(void)setDog:(dog*)aDog  
        7. {  
        8. if (_mydog!=aDog) {  
        9.         [_mydog release];  
        10.         _mydog=[aDog retain];  
        11.     }  
        12. }  
        13.   
        14. -(id)mydog{  
        15. return _mydog;  
        16. }  
        17.   
        18. -(void)callFun{  
        19. "call Fun!");  
        20.     [_mydog callFromNSObject];  
        21. }  
        22.   
        23. -(void)dealloc{  
        24.     [self setDog:nil];  
        25.     [super dealloc];  
        26. }  
        27. @end

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


          1. #import <Cocoa/Cocoa.h>  
          2.   
          3.   
          4. @interface  NSObject(myCategroy)   
          5. -(void)callFromNSObject;  
          6. @end



          1. #import "nsobject_categroy.h"  
          2.   
          3.   
          4. @implementation  NSObject(myCategroy)   
          5. -(void)callFromNSObject  
          6. {  
          7. "I AM NSOBJECT FUNCTIONS");  
          8. }  
          9. @end


          主函数:




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


          这样就会调用callFromNSObject方法

          类别主要有三个功能:

          一、利用类别分散实现

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

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

          【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

          1. 分享:
          最后一次编辑于 2023年11月08日 0

          暂无评论

          JDh7sMsPQI0Y