溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

OC的正式協(xié)議和非正式協(xié)議

發(fā)布時間:2020-06-17 01:18:00 來源:網(wǎng)絡(luò) 閱讀:282 作者:xiesiyuana 欄目:開發(fā)技術(shù)

最近看了些關(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

實現(xiàn)這個協(xié)議

mytest.h

#import <Foundation/Foundation.h> #import "myprotocol.h"  //實現(xiàn)協(xié)議 myprotocol @interface mytest : NSObject<myprotocol>  {  } - (void)showInfo; @end 
mytest.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;  @end
dog.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

person.h

#import <Foundation/Foundation.h> #import "Dog.h"  @interface Person : NSObject<dogBark> {  	Dog *_dog; }  @property (retain) Dog *dog; @end 
person.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; } 

使用非正式協(xié)議也可以實現(xiàn)委托,前面講非正式協(xié)議是使用類別來實現(xiàn)的,

同樣的是一個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; }  @end 
person類

#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]; } @end
NSObject類別的實現(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é)議和委托類別












向AI問一下細(xì)節(jié)

免責(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)容。

AI