您好,登錄后才能下訂單哦!
最近看了些關(guān)于objective-c的正式協(xié)議和非正式協(xié)議的內(nèi)容,發(fā)現(xiàn)還是有些混亂,可能是因為還不熟悉OC,對正式協(xié)議和非正式協(xié)議的使用還不是很熟練,所以想整理一下
非正式協(xié)議,是使用類別category來實現(xiàn),非正式協(xié)議是NSObject的一個類別,這樣任何類的對象都可以作為委托對象來使用,它可以列出對象能夠執(zhí)行的所有方法,這樣用來實現(xiàn)委托, 我們可以使用選擇器來判斷該非正式協(xié)議中是否有這個方法。
正式協(xié)議,是一個命名的方法列表,與非正式協(xié)議相比不同的是,它要求顯示的采用協(xié)議,采用協(xié)議的方法是在類的@interface聲明中列出協(xié)議的名稱,此時,實現(xiàn)協(xié)議的類應(yīng)該遵守協(xié)議,承諾實現(xiàn)協(xié)議中的所有方法,否則編譯器將會發(fā)出警告。
協(xié)議類似于C++的純虛函數(shù),協(xié)議只有聲明,沒有實現(xiàn),用來在子類中實現(xiàn),協(xié)議中的方法有兩類屬性,@required和@optional兩種,@required屬性的要求實現(xiàn)協(xié)議的類必須要實現(xiàn)這種方法,而@optional屬性的方法則不要求,如果不確定協(xié)議是否被實現(xiàn),可以使用respondsToSelector:@select()來判斷。
下面是一個協(xié)議的聲明和實現(xiàn)實例代碼:
聲明一個協(xié)議myprotocol
@protocol myprotocol <NSObject> @optional -(void)print:(int)value; //可選的方法 @required -(int)printValue:(int)value1 andValue:(int)value2; //必須實現(xiàn)的 @end
mytest.h
#import <Foundation/Foundation.h> #import "myprotocol.h" //實現(xiàn)協(xié)議 myprotocol @interface mytest : NSObject<myprotocol> { } - (void)showInfo; @endmytest.m
#import "mytest.h" @implementation mytest -(void)showInfo { NSLog(@"I am in showInfo"); } //實現(xiàn)協(xié)議必須實現(xiàn)的 -(int)printValue:(int)value1 andValue:(int)value2 { NSLog(@"print value1 %d,value2 %d",value1,value2); return 0; } //實現(xiàn)可選的 -(void)print:(int)value { NSLog(@"print value is %d",value); } @end使用這個協(xié)議main.m
#import <Foundation/Foundation.h> #import "mytest.h" #import "myprotocol.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; // insert code here... NSLog(@"Hello, World!"); mytest *test=[[mytest alloc]init]; [test showInfo]; [test printValue:20 andValue:30]; //print協(xié)議是可選的,所以在用之前一定要判斷是否實現(xiàn)了,不然可能會出錯,使用下面的方法 // [test print:20]; SEL sel=@selector(print:); if([test respondsToSelector:sel]){ [test print:11]; } //用協(xié)議的方式實現(xiàn) id<myprotocol> protocol =[[[mytest alloc]init]autorelease]; [protocol showInfo]; [protocol printValue:200 andValue:300]; if([protocol respondsToSelector:@selector(print:)]){ [protocol print:111]; } [test release]; [pool drain]; return 0; }下面介紹使用正式協(xié)議來實現(xiàn)代理,或者叫委托,委托是一中推向,另一個類的對象會要求委托對象來執(zhí)行它的某些操作。
下面的例子,有一個dog類,一個person類,每個person對象有一個狗,這條狗僅僅屬于這個主人,狗會定時的通知主人,也就是調(diào)用person類的一些方法,這樣在狗的類中就需要一個person的代理,要求主人調(diào)用一些方法,機制類似回調(diào),如下:
dog.h
#import <Foundation/Foundation.h> @protocol dogBark; @interface Dog : NSObject { int _ID; NSTimer *timer; int barkCount; id <dogBark> delegate; //存放狗的主人 } @property int ID; @property (assign)id <dogBark> delegate; @end //定義一個人和狗通訊的協(xié)議 protocol @protocol dogBark<NSObject> -(void)bark:(Dog*)thisDog count:(int)count; @enddog.m
#import "Dog.h" @implementation Dog @synthesize ID=_ID; @synthesize delegate; -(id)init { if(self = [super init]){ //創(chuàng)建一個定時器user,每隔1.0s 就調(diào)用updateTimer:nil,并傳遞一個參數(shù)nil timer=[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES]; } return self; } -(void) updateTimer:(id)arg { barkCount++; NSLog(@"dog bar %d",barkCount); //調(diào)用主人delegate的bark:count方法, [delegate bark:self count:barkCount]; //回調(diào)機制 } @end
#import <Foundation/Foundation.h> #import "Dog.h" @interface Person : NSObject<dogBark> { Dog *_dog; } @property (retain) Dog *dog; @endperson.m
#import "Person.h" @implementation Person @synthesize dog=_dog; -(void)setDog:(Dog*)aDog { if(_dog!=aDog){ [_dog release]; _dog=[aDog retain]; // 通知dog的主人是當(dāng)前人,self [_dog setDelegate:self]; } } //當(dāng)狗叫的時候,讓狗來調(diào)用人的方法 //這個方法來源于dogBark協(xié)議,Person類來實現(xiàn) -(void)bark:(Dog*)thisDog count:(int)count { NSLog(@"Person bark: this dog %d bark %d",[thisDog ID],count); } -(void)dealloc { self.dog=nil; [super dealloc]; } @end主函數(shù)mian.m
#import <Foundation/Foundation.h> #import "Dog.h" #import "Person.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; // insert code here... NSLog(@"Hello, World!"); Person *xiaoli = [[Person alloc]init]; Dog *dog=[[Dog alloc]init]; [dog setID:10]; [xiaoli setDog:dog]; [dog release]; //程序循環(huán)在這里 while (1) { [[NSRunLoop currentRunLoop]run]; } [xiaoli release]; [pool drain]; return 0; }
同樣的是一個dog類,一個person類,person類有一條狗,再實現(xiàn)一個NSObject的類別,在類別中實現(xiàn)一個方法,通過dog對象來調(diào)用這個方法。
#import <Cocoa/Cocoa.h> @interface dog : NSObject { int _ID; } @property int ID; @end
#import "dog.h" @implementation dog @synthesize ID=_ID; -(id)init { self=[super init]; return self; } @endperson類
#import <Cocoa/Cocoa.h> #import "dog.h" @interface person : NSObject { dog *_mydog; } -(void)setDog:(dog*)aDog; -(id)mydog; -(void)callFun; @end
#import "person.h" #import "nsobject_categroy.h" @implementation person -(void)setDog:(dog*)aDog { if (_mydog!=aDog) { [_mydog release]; _mydog=[aDog retain]; } } -(id)mydog{ return _mydog; } -(void)callFun{ NSLog(@"call Fun!"); [_mydog callFromNSObject]; } -(void)dealloc{ [self setDog:nil]; [super dealloc]; } @endNSObject類別的實現(xiàn),也就是非正式協(xié)議
#import <Cocoa/Cocoa.h> @interface NSObject(myCategroy) -(void)callFromNSObject; @end
#import "nsobject_categroy.h" @implementation NSObject(myCategroy) -(void)callFromNSObject { NSLog(@"I AM NSOBJECT FUNCTIONS"); } @end主函數(shù):
#import <Foundation/Foundation.h> #import "person.h" #import "dog.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; // insert code here... NSLog(@"Hello, World!"); dog *d=[[dog alloc]init]; [d setID:10]; person *p=[[person alloc]init]; [p setDog:d]; [p callFun]; [p release]; [pool drain]; return 0; }這樣就會調(diào)用callFromNSObject方法
類別主要有三個功能:
一、利用類別分散實現(xiàn)
二、利用類別創(chuàng)建前向引用,可以實現(xiàn)私有函數(shù)
三、非正式協(xié)議和委托類別
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。