中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

讀書總結(jié)之NSObject

2018-07-20    來(lái)源:編程學(xué)習(xí)網(wǎng)

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬(wàn)Linux鏡像隨意使用

使用 Objectvice-C 進(jìn)行全面對(duì)象編程時(shí),除了需要知道語(yǔ)言本身的語(yǔ)法和面向?qū)ο蟮闹R(shí)外,還需要了解Objectvice-C的根類 NSObject 的信息。

NSObject

根類的作用

作為一門動(dòng)態(tài)編程語(yǔ)言,Objectstvice-C有很多動(dòng)態(tài)的特性,因此,Objectvice-C不進(jìn)需要編譯環(huán)境,同時(shí)還需要一個(gè)運(yùn)行時(shí)系統(tǒng)(runtime system)來(lái)執(zhí)行編譯好的代碼。運(yùn)行時(shí)系統(tǒng)扮演的角色類似于Objectvice-C的操作系統(tǒng),他負(fù)責(zé)完成對(duì)象生成、釋放時(shí)的內(nèi)存管理、發(fā)來(lái)的消息查找對(duì)應(yīng)的處理方法等工作。

通常情況下,程序無(wú)法直接使用運(yùn)行時(shí)系統(tǒng)提供的功能。根類方法提供了運(yùn)行時(shí)系統(tǒng)的基本工恩給你。繼承了 NSObject 的所有類都可以自由的使用運(yùn)行時(shí)系統(tǒng)的功能,也就是說(shuō),根類就想到于系統(tǒng)的一個(gè)借口。

根類通過(guò)哪些方式提供了哪些功能對(duì)系統(tǒng)有很大的影響。因此,根類不同的系統(tǒng)之間是無(wú)法開(kāi)發(fā)出通用的程序的。

Cocoa 是以O(shè)PENSTEPDE的核心 API 為基礎(chǔ)發(fā)展起來(lái)的。OPENSTEP的前身為 NeXTstep。在 NeXTstep 時(shí)代,根類是累 Object,而在 OPENSTEP 時(shí)代,根類則變?yōu)榱?NSObject,同時(shí)類的設(shè)計(jì)也得到了大幅度的改進(jìn)。

<!--more-->

NSArray,NSString 等等NS前綴類、函數(shù)歸屬于cocoa Fundation基礎(chǔ)類庫(kù),其"NS”的由來(lái)?yè)?jù)說(shuō)是這樣的:?jiǎn)滩妓贡惶O果開(kāi)除后,創(chuàng)立了NeSt公司,而cocoa Fundation基礎(chǔ)類庫(kù)就是出自于NeST公司,NeST中的"NS"被作為Fundation中所有成員的前綴

類和實(shí)例

NSObject 只是一個(gè)實(shí)例變量,就是 Class 類型的變量 isa。isa 用于表示實(shí)例對(duì)象屬于哪個(gè)類對(duì)象。因?yàn)?isa 決定著實(shí)例變量和類的關(guān)系,非常重要,所以子類不可以修改 isa 的值。另外,也不能通過(guò)直接訪問(wèn) isa 來(lái)查詢實(shí)例變量到底屬于哪個(gè)類,而是要通過(guò)實(shí)例方法 class 來(lái)完成查詢。

在運(yùn)行時(shí)的代碼中我們可以查看到objc_class的定義如下:

/// An opaque type that represents an Objective-C class. typedef struct objc_class *Class; /// Represents an instance of a class. struct objc_object {
    Class isa  OBJC_ISA_AVAILABILITY;
};

下面對(duì)類和實(shí)例變量的相關(guān)方法進(jìn)行說(shuō)明。NSObject 的方法與其說(shuō)是為自己定義的,不如說(shuō)是為了其子類和所有實(shí)例對(duì)象而定義的。

- (class) class
    返回消息接收者所屬類的類對(duì)象

+ (class) class
    返回類型對(duì)
    雖然可以使用類名作為消息的接受者來(lái)調(diào)用類方法,但類對(duì)象是其他消息的參數(shù),或者將類對(duì)象賦值給變量的時(shí)候,需要通過(guò)這個(gè)方法來(lái)獲取類的參數(shù)

- (id) self 返回接受者自身。是一個(gè)無(wú)任何實(shí)際動(dòng)作但很有用的方法。

-(BOOL) isMemberOfClass: (Class) aClass
    判斷消息接受者是不是參數(shù) aClass 類的對(duì)象

-(BOOL) isKindOfClass: (Class) aClass
    判斷消息接受者是否是參數(shù) aClass 類或者 aClass 的子類的實(shí)例。這個(gè)函數(shù)和 isMemberOfClass:的區(qū)別在于當(dāng)消息的接受者是 aClass 的子類的實(shí)例時(shí)也返回 YES。

- (BOOL) isSubclassOfClass: (Class) aClass
    判斷消息接受者是不是參數(shù) aClass 的子類或自身,如果是則返回 YES - (Class) superclass
    返回消息接受者所在類的父類的類對(duì)象。

+ (Class) superclass
    返回消息接收類的父類和類對(duì)象

實(shí)例對(duì)象的生成和釋放

+ (id) alloc
    生成消息接收類的實(shí)例對(duì)象。通常和 init 或者 init 開(kāi)頭的方法連用,生成實(shí)例化對(duì)象的同事需要對(duì)其進(jìn)行初始化。子類中不潤(rùn)徐重寫 alloc 方法

+ (void) dealloc
    釋放實(shí)例對(duì)象。dealloc 被稱之為 release 的結(jié)果調(diào)用。除了在子類中重寫 dealloc 的情況之外,程序不潤(rùn)徐直接調(diào)用 dealloc

- (oneway void)release
    將消息接受者的引用計(jì)數(shù)減1.引用計(jì)數(shù)變?yōu)?span id="sfhk6bkxn"    class="hljs-number">0時(shí),dealloc 方法被調(diào)用,消息接受者被釋放

- (id)retain
    為消息接收者的引用計(jì)數(shù)加1,同事返回消息接收者

- (id)autorelease
    把消息的接受者加入到自動(dòng)釋放池中,同事返回消息接受者

- (NSUinteger) retainCount
    返回消息接受者的引用計(jì)數(shù),可在調(diào)試時(shí)使用這個(gè)方法。NSUInteger 是無(wú)符號(hào)證書類型

- (void)finalize
    垃圾收集器在釋放接受者對(duì)象之前會(huì)執(zhí)行該 finalize 方法。

上面從 dealloc 到 retainCount 都是手動(dòng)引用計(jì)數(shù)管理內(nèi)存時(shí)使用的方法,使用 ARC 時(shí)不可用。finalize 僅供垃圾回收有效時(shí)使用。

初始化

- (id) init init 可對(duì) alloc 生成的實(shí)例對(duì)象進(jìn)行初始化。子類中可以重寫 init 或者自定義的心的以 init 開(kāi)頭的初始化函數(shù)。

+ (void)initialize
    被用于類的初始化,也就是對(duì)類中共同使用的變量進(jìn)行初始化設(shè)定等。這個(gè)方法會(huì)在類收到第一個(gè)消息之前被自動(dòng)執(zhí)行,不需手動(dòng)調(diào)用

+ (id) new new 是 alloc 和 init 的組合。new 方法返回的實(shí)例對(duì)象的所有者就是調(diào)用 new 方法的對(duì)象。但是把 alloc 和 init 組合定義為 new 沒(méi)有什么優(yōu)點(diǎn),并不建議使用。
    根據(jù)類的實(shí)現(xiàn)不同,new 方法并不會(huì)每次都返回一個(gè)全新的實(shí)例對(duì)象。有時(shí)new 方法會(huì)返回對(duì)象池中預(yù)先生成的對(duì)象,也有可能每次都返回同一個(gè)對(duì)象。

對(duì)象的比較

-(BOOL) isEqual: (id) anObject
    消息的接受者如果和參數(shù) anObject 相等則返回 YES - (NSUInteger) hash
    把對(duì)象放入容器的時(shí)候,返回系統(tǒng)內(nèi)部用的散列表

原則上來(lái)講,具有相同 id 值也就是同一個(gè)指針指向的對(duì)象被認(rèn)為是相等的。而子類在這個(gè)基礎(chǔ)上進(jìn)行了擴(kuò)展,把擁有相同值認(rèn)為是相等。我們可以根據(jù)需求對(duì)“想通知”激進(jìn)型定義,但一般都會(huì)讓具備“相同值”的對(duì)象返回相同的散列表,因此就需要對(duì)散列表方法進(jìn)行重新定義。而反之則并不成立,也就是說(shuō),散列值相等的兩個(gè)對(duì)象不一定相等。

另外,有的累中還自定義了 compare:或者isEqualTo 之類的方法。至于到底是哪個(gè)方法或者自定義類的時(shí)候是否需要定義比較的方法,都需要根據(jù)目的和類的內(nèi)容做具體分析。

對(duì)象的內(nèi)容描述

+ (NSString*) description
    返回一個(gè) NSString 類型的字符串,表示消息接受者所屬類的內(nèi)容。通常是這個(gè)類的名稱。

- (NSString*)description
    返回一個(gè) NSString 類型的字符串,表示消息接受者的實(shí)例對(duì)象的內(nèi)容。通常是類名家 id 值。子類中可以重新定義 description 的返回值。例如 NSString的實(shí)例會(huì)返回字符串的內(nèi)容,NSArray 的實(shí)例會(huì)對(duì)數(shù)組中的每一個(gè)元素調(diào)用 description,然后將調(diào)用結(jié)果用句號(hào)進(jìn)行分割,并且一起返回。

消息發(fā)送機(jī)制

選擇器和 SEL 類型

至今為止我們把選擇器(方法名)和消息關(guān)鍵字放在一起進(jìn)行說(shuō)明。程序中的方法名(選擇器)在便有被一個(gè)內(nèi)部標(biāo)識(shí)符所代替,這個(gè)內(nèi)部標(biāo)識(shí)符所對(duì)應(yīng)的數(shù)據(jù)類型就是 SEL 類型。

Objective-C為了能夠在程序中操作編譯后的選擇器,定義了@selector()指令。通過(guò)使用@selector()指令,就可以直接飲用編譯后的選擇器。使用方法如下:

@selector(mutableCopy) @selector(compare:) @selector(replaceObjectAtIndex:withObject:)

也可以聲明 SEL 類型的變量

選擇器不同的情況下,編譯器轉(zhuǎn)換后生成的 SEL 類型的值也一定不同,相同的算擇期對(duì)應(yīng)的 SEL 類型的值一定相同。Objective-C的程序員不需要知道選擇器對(duì)應(yīng)的 SEL 類型的值到底是什么,具體的值是和處理器相關(guān)的。但是如果 SEL 類型的便利功能無(wú)效的話,可設(shè)其為 NULL,或者也可以使用(SEL)0這種常見(jiàn)的表達(dá)方式

可以使用 SEL 類型的變量來(lái)發(fā)送消息,為此,NSObject 中準(zhǔn)備了如下方法

-(id)performSelector: (SEL) aSelector
    向消息的接收者發(fā)送 aSelector代表的消息,返回這個(gè)消息的執(zhí)行結(jié)果

-(id)performSelector: (SEL) aSelector 
            withObject: (id) anObject
    與上面的方法一直,不過(guò)可以傳遞參數(shù)

例如下面兩個(gè)消息表達(dá)式進(jìn)行的處理是相同的

[target description] [targ performSelector: @selector(description)];

下面的例子展示了如何根據(jù)條件動(dòng)態(tài)決定執(zhí)行那個(gè)方法

SEL method = (void1) ? @selector(activate:) : @selector(hide:); id obj = (cond2) ? MyDocument : defaultDocument;
[target performSelector:method withObject:obj]

這種調(diào)用方式很想 C 語(yǔ)言中函數(shù)指針的用法,使用函數(shù)指針可以實(shí)現(xiàn)和上面的程序同樣的功能。

函數(shù)指針是函數(shù)在內(nèi)存中的地址。指針對(duì)應(yīng)的函數(shù)是在編譯的時(shí)候決定的,不能夠執(zhí)行指定之外的函數(shù)。SEL 類型就相當(dāng)于方法名,根據(jù)消息接受者的不同(上例子中 target 的賦值),來(lái)動(dòng)態(tài)執(zhí)行不同的方法。

通過(guò) SEL 類型來(lái)指定要中子星的方法,這就是 Objectivce-C消息發(fā)送的方式。也正是通過(guò)這種方法才實(shí)現(xiàn)了 Objectivce-C的動(dòng)態(tài)性

消息搜索

對(duì)象收到一個(gè)消息后執(zhí)行哪個(gè)方法是動(dòng)態(tài)決定的。

所有的實(shí)例變量都存在一個(gè) Class 類型的 isa 變量,它就是類對(duì)象。當(dāng)收到消息后,運(yùn)行時(shí)系統(tǒng)會(huì)檢查類內(nèi)是否有和這個(gè)消息選擇器相同的方法,如果有就執(zhí)行對(duì)應(yīng)的方法,如果沒(méi)有就通過(guò)類對(duì)象中指向父類的指針來(lái)查找父類中是否有對(duì)應(yīng)的方法。如果一直找到根類都沒(méi)有找到對(duì)應(yīng)的方法,就會(huì)提示執(zhí)行時(shí)錯(cuò)誤。

如果每次收到消息都需要查找對(duì)應(yīng)的方法的話,消息發(fā)送過(guò)程的開(kāi)銷就會(huì)很大,是針對(duì)這種情況,運(yùn)行時(shí)內(nèi)部會(huì)緩存一個(gè)散列表,表中記錄著某個(gè)類擁有和什么樣的選擇器相對(duì)應(yīng)的方法、方法被定義在何處等信息。這樣一來(lái),當(dāng)下次在收到同樣的消息時(shí),直接利用上次緩存好的信息即可。

NSObject 中定義了可以動(dòng)態(tài)檢查一個(gè)對(duì)象是否能夠響應(yīng)某個(gè)選擇器的方法。

- (BOOL) respondsToSelector: (SEL) aSelector
    查詢消息的接收者中是否能夠響應(yīng) aSelector 的方法,包括從父類繼承來(lái)的方法,如果存在的話則返回 YES - (BOOL) instancesRespondToSelector: (SEL) aSelector
    查詢消息的接收者所屬的類中是否能夠響應(yīng) aSelector 的實(shí)例方法,如果存在的話則返回 YES

一函數(shù)的形式來(lái)調(diào)用方法

類中定義的方法通常是以函數(shù)的形式來(lái)實(shí)現(xiàn)的,但通常在編程的時(shí)候并不會(huì)直接操作方法所對(duì)應(yīng)的函數(shù)。

但如果想盡可能第讓程序更快一點(diǎn),或者需要按照 C 語(yǔ)言的管理傳遞函數(shù)指針的時(shí)候,可以直接調(diào)用方法對(duì)應(yīng)的函數(shù),以節(jié)省發(fā)送消息的開(kāi)銷。另外執(zhí)行時(shí)動(dòng)態(tài)加載方法的定義等時(shí),也可以將方法作為函數(shù)調(diào)用。但是需要注意的是,如果以函數(shù)的形式來(lái)調(diào)用方法的話,將無(wú)法利用面向?qū)ο蟮膭?dòng)態(tài)綁定等功能。雖然消息發(fā)送同函數(shù)調(diào)用相比確實(shí)慢一點(diǎn),但卻有面向?qū)ο蟮膭?dòng)態(tài)綁定、多態(tài)等優(yōu)點(diǎn)。同這些優(yōu)點(diǎn)相比,速度上略微的損失是不值得一提的。而其實(shí)消息發(fā)送的速度也非常的快。

通過(guò)使用下面的方法,可以獲得某個(gè)對(duì)象持有的方法的函數(shù)指針,這些方法都被定義在 NSObject 中。

- (IMP) methodForSelector: (SEL) aSelector
    搜索和執(zhí)行選擇器對(duì)應(yīng)的方法,并返回指向該方法實(shí)現(xiàn)的函數(shù)指針。實(shí)例對(duì)象和類對(duì)象都可以使用這個(gè)方法。對(duì)實(shí)例對(duì)象使用時(shí),會(huì)返回實(shí)例方法對(duì)應(yīng)的函數(shù),對(duì)類對(duì)象使用時(shí),會(huì)返回類對(duì)象對(duì)應(yīng)的函數(shù)
+ (IMP) instanceMethodForSelector: (SEL)aSelector;
    搜索和制定選擇器相對(duì)應(yīng)的實(shí)例方法,并返回該指向?qū)嵗椒▽?shí)現(xiàn)的函數(shù)指針

IMP 是“implemention”的縮寫,它是一個(gè)函數(shù)指針,指向了方法實(shí)現(xiàn)代碼的入口

IMP 的定義為:

#if !OBJC_OLD_DISPATCH_PROTOTYPES typedef void (*IMP)(void /* id, SEL, ... */ ); #else typedef id (*IMP)(id, SEL, ...); #endif

這個(gè)被指向的函數(shù)包括 id(self 指針)、調(diào)用的 SEL(方法名),以及其他參數(shù)

例如:

- (id)setBox:(id)obj1 title:(id)obj2;

foo 是這個(gè)方法所屬類的一個(gè)實(shí)例變量。獲取指向 setBox 的函數(shù)指針,并且通過(guò)該指針進(jìn)行函數(shù)調(diào)用的過(guò)程如下:

IMP funcp;
    funcp = [foo methodForSelector:@selector[setBox:title]];
    xyz = (*funcp)(foo,@selector[setBox:title:],param1,param2)

類對(duì)象和跟對(duì)象

因?yàn)槔蹖?duì)象也是一個(gè)對(duì)象,所以累對(duì)象可以作為根類 NSObject 的某個(gè)子類的對(duì)象來(lái)使用。下面這句話看上去好像比較奇怪,但是實(shí)際上他是正確的,會(huì)返回 YES

[NSString class] isKindOfClass:[NSObject class]]

這就說(shuō)明了相當(dāng)于類對(duì)象的類的對(duì)象是存在的。而類對(duì)象的類就被叫做元類(metaclass)。實(shí)例對(duì)象(instance object)所屬的類是 class,類對(duì)象(class object)所屬的類是 metaclass。

Objective-C 中的很多概念都來(lái)源于 Smalltalk,元類的概念就是其中之一。但現(xiàn)在的 Objective-C中已經(jīng)不存在元類的概念了,程序中不能操作元類。用于表示對(duì)象的 id 類型和表示類的 Class 類實(shí)際上都是指向結(jié)構(gòu)體的指針。被詳細(xì)定義在/usr/include/objc 下面的 objc.h 頭文件中。通過(guò)查看 objc.h 中 id和 Class 的定義,就會(huì)發(fā)現(xiàn)類和元類的關(guān)系如圖所示。Objective-C2.0更新了基本的數(shù)據(jù)結(jié)構(gòu),但是沒(méi)有改變類和元類的關(guān)系。


類 A 是 NSObject 的子類,類 B是 A 的子類。類對(duì)象和實(shí)例對(duì)象都存在一個(gè)成員變量 isa,它是一個(gè) objc_class 類型的指針

圖中帶有 isa 的實(shí)現(xiàn)表明了 isa 指向的對(duì)象,帶有 super_class 的虛線則表明了父類的關(guān)系。

類對(duì)象中保存的是實(shí)例方法,元對(duì)象中保存的是累方法。通過(guò)這樣的定義能夠統(tǒng)一實(shí)現(xiàn)實(shí)例方法和類方法的調(diào)用機(jī)制。

因?yàn)榫幊虝r(shí)不可以直接操作元類,所以并不需要完全了解圖中的細(xì)節(jié)。大家只需要記住任何一個(gè)類對(duì)象都是繼承了根類的元對(duì)象的一個(gè)實(shí)例即可。也就是說(shuō),類對(duì)象可以執(zhí)行根類對(duì)象的實(shí)例方法。

例如,類對(duì)象可以執(zhí)行 NSObject 的實(shí)例方法 performSelector:和 respondsToSelector:。當(dāng)然提前是沒(méi)有將這些方法作為類方法再次定義。

下面讓我們總結(jié)一下。其中(1)和(2)我們已經(jīng)介紹過(guò)了。(3)比較不容易理解,

  1. 所有類的實(shí)例對(duì)象都可以執(zhí)行根類的實(shí)例方法

    • 如果在派生類中重新定義了實(shí)例方法,新定義的方法會(huì)被執(zhí)行
  2. 所有類的類對(duì)象都可以執(zhí)行根類的類方法

    • 如果在派生類中重新定義了類方法,新定義的方法會(huì)被執(zhí)行
  3. 所有類的類對(duì)象都可以執(zhí)行根類的實(shí)例方法

    • 即使在派生類中重新定義了實(shí)例方法,根類中的方法也會(huì)被執(zhí)行
    • 如果在派生類中將實(shí)例方法作為類方法重新定義了的話,新定義的方法會(huì)被執(zhí)行

文/向心(簡(jiǎn)書作者)
原文鏈接:http://www.jianshu.com/p/2c59646e5cae

標(biāo)簽: isp 代碼 搜索

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:軟件架構(gòu)到底是要解決什么問(wèn)題?

下一篇:什么是軟件