天天看點

Mac/iPhone Category & Protocol

http://blog.codingmylife.com/?p=41

Categories

#import “ClassName.h”

@interface ClassName ( CategoryName )

// method declarations

@end

#import “ClassName+CategoryName.h”

@implementation ClassName ( CategoryName )

// method definitions

@end

For example

@interface MyObject : NSObject{

NSNumber *number;

}

- (NSNumber *)number;

@end

@interface MyObject (Setter)

- (void)setNumber:(NSNumber *)newNumber;

@end

@implementation MyObject

- (NSNumber *)number{

return number;

}

- (void)setNumber(NSNumber *)newNumber{

number = newNumber;

}

@end

Protocol

@protocol MyProtocol

- (void)requiredMethod;

@optional

- (void)anOptionalMethod;

- (void)anotherOptionalMethod;

@required

- (void)anotherRequiredMethod;

@end

For example

1 2 3 4 5 6 7 8 9 10

Inherit multiple protocol. @interface Formatter : NSObject Instance. Protocol *myXMLSupportProtocol = @protocol(MyXMLSupport);

Check if methods are declared

if(![receiver conformsToProtocol:@protocol(MyXMLSupport)]){

//Object does not conform to MyXMLSupport protocol

//If you are expecting receiver to implement methods declared in the

//MyXMLSupport protocol, this is probably an error

}

-(NSString*)formattingService:(id)anObject;

———————————————————————

http://icocoa.cn/ocsection/oc-tips/60-category-vs-protocol

Category

Category提供了一種比繼承(inheritance)更為簡潔的方法來對class進行擴充,我們可以為任何已經存在的class添加方法(不包括資料成員)卻不需要通路該class的實作檔案。

新添加的方法和原有的方法具有同等的地位,可以通路class的資料成員,并且完全植入到class的繼承體系之中,子類同樣會繼承新添加的方法。 利用category對類進行擴充可以避免使類的繼承體系過于臃腫,複雜,降低了維護成本。另外,新添加的方法如果和已經存在的方法具有相同的 prototype,那麼新添加的方法将會覆寫已經存在的方法,也就是category使得使得在沒有源檔案時修改已存在class的 functionality或者清除bug成為可能,所有該class的對象的行為都将發生變化,這一點是繼承無法達到的。

Category的缺點:

如果一個已經存在的方法被新方法覆寫,那麼将沒有任何途徑可以對舊方法進行調用。這一點和繼承是不同的,子類對父類成員函數重寫(override),但我們依然可以對父類中的被重寫的成員函數進行調用。

如果有多個category對同一個class的成員函數進行重寫,那麼具體的行為是未定義。

Category的應用:

對類進行擴充或patch。

使用category或(anonymous category)來模拟實作private method。

使用category(informal protocol)來實作delegation,在cocoa framework中就大量使用了category來聲明delegate methods。

利用category把一個龐大的class劃分為小塊兒來分别進行開發,進而将functionality更好的進行劃分,利于維護。

Protocol

根據字面意思,protocol就是一個協定,一個contract。一個class如果采用了某個protocol,那麼它就必須要遵守這個協 議。從另外一個角度,隻要我遵守了某個protocol或者标準,那我就可以和其它的類進行互動,而且其它類并不需要知道我的内部是如何實作的,例如 一套組合音響,隻要其中的dvd,錄音機等裝置采用的是标準接口,那麼它就可以很輕易的被放入這個音響系統中,發揮自己的功能。回到objective c,在cocoa touch framework中利用protocol聲明delegate methods是同樣的道理,cocoa touch framework,你們想要提供自定義功能或者響應某個事件嗎?很簡單,隻要你們的功能遵守我提供的protocol。(注意,這裡之是以采 用protocol來聲明delegate methods,而不是cocoa framework中使用informal protocol(category),是因為objective c 2.0 引入了@optional methods,iphone又是在objective c 2.0之後出來的,是以cocoa touch framework中就用protocol替代informal protocol來聲明delegate methods。)其實plugin,回調函數都是和protocol相同的思路。

另一方面,objective c隻支援單一繼承,protocol提供了一個途徑來達到多重繼承的目的。

另一介紹 Protocol文章:

http://www.cocoachina.com/bbs/read.php?tid-50601.html

協定,是通過網絡,計算機使用者進行通訊後,互相進行約定規定的集合。兩個類進行通訊,用協定就比較友善。下面是 CocoaChina 版主“angellixf”為新手寫的協定入門介紹以及代碼例子,希望對剛入門開發者有所幫助

一、說明

1.協定聲明了可以被任何類實作的方法

2.協定不是類,它是定義了一個其他對象可以實作的接口

3.如果在某個類中實作了協定中的某個方法,也就是這個類實作了那個協定。

4.協定經常用來實作委托對象。一個委托對象是一種用來協同或者代表其他對象的特殊對象。

5:委托,就是調用自己定義方法,别的類來實作。

6.新特性說明

@optional預編譯指令:表示可以選擇實作的方法

@required預編譯指令:表示必須強制實作的方法

二、定義

.h

@protocol ContactCtrlDelegate

-(void)DismissContactsCtrl;

@end

@interface ContactsCtrl : UIViewController {

id <ContactCtrlDelegate> delegate;

}

@property (nonatomic, assign) id <ContactCtrlDelegate> delegate;

.m

三、例子

例如:UITextView

@protocol UITextViewDelegate <NSObject>

@optional

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView;

- (BOOL)textViewShouldEndEditing:(UITextView *)textView;

- (void)textViewDidBeginEditing:(UITextView *)textView;

- (void)textViewDidEndEditing:(UITextView *)textView;

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;

- (void)textViewDidChange:(UITextView *)textView;

- (void)textViewDidChangeSelection:(UITextView *)textView;

@end

如果要調用以上這些方法,就必須設定UITextView的委托:TextView.delegate = self;

四、Demo

1、ContactsCtrl.h

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

#import <UIKit/UIKit.h>

//定義協定

@protocol ContactCtrlDelegate

-(void)DismissContactsCtrl;

@end

@interface ContactsCtrl : UIViewController {

IBOutlet UINavigationBar *ContactNavBar;

id <ContactCtrlDelegate> delegate;

}

@property (nonatomic, assign) id <ContactCtrlDelegate> delegate;

-(IBAction)canCelBtn:(id)sender;

@end

1

2、ContactsCtrl.m

1

@implementation ContactsCtrl

@synthesize delegate;

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.

- (void)viewDidLoad {

[super viewDidLoad];

ContactNavBar.topItem.prompt = @"選取聯系人發送短信";

}

//調用協定中的方法

-(IBAction)canCelBtn:(id)sender{

[delegate DismissContactsCtrl];

}

3、ProtocolDemoCtrl.h

1 2 3 4 5

#import <UIKit/UIKit.h>

#import "ContactsCtrl.h"

@interface ProtocolDemoCtrl : UIViewController <ContactCtrlDelegate>{//添加委托

ContactsCtrl *contactsView;

}

4、ProtocolDemoCtrl.m

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

#import "ProtocolDemoCtrl.h"

#define BARBUTTONADD(SELECTOR) [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:SELECTOR] autorelease];

@implementation ProtocolDemoCtrl

@synthesize contactsView;

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.

- (void)viewDidLoad {

[super viewDidLoad];

self.navigationItem.rightBarButtonItem = BARBUTTONADD(@selector(addContactAction:));

}

- (void)addContactAction:(id)sender{

ContactsCtrl *contactView = [[ContactsCtrl alloc] initWithNibName:@"ContactsCtrl" bundle:nil];

self.contactsView = contactView;

contactsView.delegate = self;//設定委托

[self presentModalViewController:contactsView animated:YES];

[contactView release];

}

//實作ContactCtrlDelegate協定中的方法

-(void)DismissContactsCtrl{

[contactsView dismissModalViewControllerAnimated:YES];

}