天天看點

objective-C 類别/協定。

第十二章 類别

類别:

命名方式: 類名稱+類别名稱。

在Xcode中可以在建立檔案的類别中找到 Objective-C category圖示。

@interface部分

類别的聲明看起來非常像類的聲明:

@interface NSString (NumberConvenience)

 -(NSNumber *) lengthAsNumber; 

@end

括号内(NumberConverience)叫做類别名,且它是添加給NSString類的。 整句話可以了解為:我們為NSString類添加了一個名為NumberConverience的類别。

可以在類别中添加屬性,但不能添加執行個體變量,而且屬性必須是@dynamic(動态)類型的,添加屬性的好處在于你可以通過點表達式來通路setter和getter方法。

@implementation

 @implementation NSString (NumberConvenience)

-(NSNumber *) lengthAsNumber{

NSUInteger length = [self length];

return ([NSNumber numberWithUnsignedInt:length]);

}

類别的優勢:

3個用途:1.将類對實作代碼分散到多個不同的檔案或者架構中。

2.建立對私有方法的前向引用。

3.向對象添加非正式協定。(informal protocol)

類别的缺陷:

1.無法向類中添加新的執行個體變量,類别沒有空間容納執行個體變量。

2.名稱沖突,也就是類别中的方法與現有的方法重名。當發生沖突的時候,類别具有更高的優先級。你的類别方法将會完全取代初始方法,導緻初始方法不可用。

(使用全局字典來存儲對象與你想要關聯的額外變量之間的映射可以克服類别無法增加執行個體變量的局限。)

一個特殊的類别:類擴充。

特點:1.不需要名字。2.你可以在包含你的源代碼多類(也就是自己的類)中使用它。3.你可以添加執行個體變量。4.你可以将隻讀權限改成可讀寫的權限。5.建立數量不限。

@interface Things : NSObject

@property (assign) NSInteger thing1;

@property (readonly,assign ) NSInteger thing2;

-(void) resetAllValues;

@interface Thing ()

{

    NSInteger thing4;

@property (readwrite,assign) NSInteger thing2;

@property (assign) NSInteger thing3;

這裡沒有繼承的父類,我們所做的基本上就是擷取Things類,并通過添加私有屬性和方法來擴充它。

常用的政策是将類别置于實作檔案多最前面。在通路其他類的私有方法時,隻要在類别中聲明這些方法編譯器就不會産生警告。

應用程式不可以通路類裡面的私有變量和方法,否則将不能通過App Store。

非正式協定和委托類别

Cocoa中的類經常會有一種名為委托的技術,委托是一種對象,由另一個類請求執行某些工作。

run循環是一種Cocoa概念,它在等待某些事情發生之前一直處于阻塞狀态,既不執行任何代碼。除了監聽網絡流量之外,run循環還處理像等待事件,(按鍵或滑鼠單擊)之類的操作。

#import <Foundation/Foundation.h>

@interface ITunesFinder : NSObject <NSNetServiceBrowserDelegate>

再nsobject後使用了NSNetServiceBrowserDelegate協定 它告訴編譯器和其他對象,該類符合這個名稱點協定并實作了其方法。

委托對象隻需要實作已經打算調用的方法即可。

托管強調類别的另一種應用:被發送給托管對象的方法可以聲明為一個NSObject的類别。

NSNetServiceBrowser的實作可以将這些消息之一發送給任何對象,無論這些對象實際上屬于哪個類,這也意味着隻要實作了委托方法,任何類的對象都可以成為委托對象。

建立一個NSObject類别稱為建立一個非正式的協定。非正式協定隻是一種表達式,他表示“這裡有一些你可能希望實作的方法,你可以使用它們更好的完成工作。”

選擇(selector)器隻是一個方法的名稱,但他以OC運作時使用特殊方式編碼,以快速執行查詢。

NSObject提供了一個名為respondsToSelector:的方法,該方法用來詢問對象以确定其是否能夠響應某個特定點消息。

Car *car = [[Car alloc] init];

        if ([car respondsToSelector:@selector(setEngine:)]) {

            NSLog(@"yo yo ..");

        }

這段代碼可以正常輸出yo yo .. ,因為Car類的對象确實能夠響應setEngine:消息。

為了确認托管對象能否響應消息,NSNetServiceBrowser将調用respondsToSelector:@selector(netServiceBrowser:didFindService:moreComing:)。如果該托管對象能夠響應給定的消息,則浏覽器向該對象發送此消息。否則浏覽器将暫時忽略托管對象,繼續正常運作。

選擇器可以被傳遞,可以用作方法的參數使用,甚至可以作為執行個體變量被存儲。

Foundation架構中的NSTimer就是這樣的類,它能夠反複大向一個對象發送消息。

本章總結:

類别的概念,功能。類擴充,選擇器。

這一章看起來比較容易了解,但是卻不清楚該怎麼用。。```

第十三章 協定

     正式協定:

    包含了方法和屬性的有名稱清單,但與非正式協定不同的是正式協定要求顯式的采用。方法是在類的@interface聲明中列出協定的名稱。采用協定就意味着你承諾實作該協定所有方法。否則将得到警告。

通常可以将NSObject作為根協定,但是與NSObject類不同,NSObject類符合NSObject協定,這意味着所有對象都符合NSObject協定。

id類型表示一個可以指向任何類型的對象的指針,它是一個泛型對象類型。你可以講任何對象複制給一個id類型的變量,反之亦可。

NSControl類中有一個名為setObjectValue:的方法,該方法要求對象追求NSCopying協定: -(void) setObjectValue: (id<NSCopying>) object;

在協定中如果增加了兩個協定修飾符: @optional 和 @required 。在這兩個修飾符之間的方法可以選擇性的實作。

委托(delegation)方法:

  委托就是某個對象指定另一個對象處理某些特定的設計模式。

-(id <NSNetServiceBrowserDelegate>) delegate;

-(void) setDelegate:(id <NSNetServiceBrowserDelegate>) delegate;

 第一個方法會傳回目前的委托對象(如果沒有則傳回nil),第二個是用來設定委托的,參數的委托類型告訴我們,隻要遵守所需的協定,就可以設定任意對象為委托。

繼續閱讀