成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

深入學(xué)習(xí)Objective-C語(yǔ)言的動(dòng)態(tài)特性

移動(dòng)開(kāi)發(fā) iOS
動(dòng)態(tài)特性是在Cocoa程序開(kāi)發(fā)時(shí)非常常用的語(yǔ)言特性,而在這之后,OC在底層也提供了相當(dāng)豐富的運(yùn)行時(shí)的特性,比如枚舉類(lèi)屬性方法、獲取方 法實(shí)現(xiàn)等等。雖然在平常的Cocoa開(kāi)發(fā)中這些較底層的運(yùn)行特性基本用不著,但是在某些情況下如果你知道這些特性并合理加以運(yùn)用的話(huà),往往能事半功倍。

[[117506]]

Objective-C具有相當(dāng)多的動(dòng)態(tài)特性,基本的,也是經(jīng)常被提到和用到的有動(dòng)態(tài)類(lèi)型(Dynamic typing),動(dòng)態(tài)綁定(Dynamic binding)和動(dòng)態(tài)加載(Dynamic loading)。

這些動(dòng)態(tài)特性都是在Cocoa程序開(kāi)發(fā)時(shí)非常常用的語(yǔ)言特性,而在這之后,OC在底層也提供了相當(dāng)豐富的運(yùn)行時(shí)的特性,比如枚舉類(lèi)屬性方法、獲取方 法實(shí)現(xiàn)等等。雖然在平常的Cocoa開(kāi)發(fā)中這些較底層的運(yùn)行特性基本用不著,但是在某些情況下如果你知道這些特性并合理加以運(yùn)用的話(huà),往往能事半功倍~

動(dòng)態(tài)特性基礎(chǔ)

1、動(dòng)態(tài)類(lèi)型

即運(yùn)行時(shí)再?zèng)Q定對(duì)象的類(lèi)型。這類(lèi)動(dòng)態(tài)特性在日常應(yīng)用中非常常見(jiàn),簡(jiǎn)單說(shuō)就是id類(lèi)型。id類(lèi)型即通用的對(duì)象類(lèi),任何對(duì)象都可以被id指針?biāo)福趯?shí)際使用中,往往使用introspection來(lái)確定該對(duì)象的實(shí)際所屬類(lèi):

  1. id obj = someInstance;   
  2. if ([obj isKindOfClass:someClass])   
  3.     someClass *classSpecifiedInstance = (someClass *)obj; 
  4.     // Do Something to classSpecifiedInstance which now is an instance of someClass 
  5.     //... 

-isMemberOfClass: 是 NSObject 的方法,用以確定某個(gè) NSObject 對(duì)象是否是某個(gè)類(lèi)的成員。與之相似的為 -isKindOfClass:,可以用以確定某個(gè)對(duì)象是否是某個(gè)類(lèi)或其子類(lèi)的成員。這兩個(gè)方法為典型的introspection方法。在確定對(duì)象為某類(lèi)成員后,可以安全地進(jìn)行強(qiáng)制轉(zhuǎn)換,繼續(xù)之后的工作。

2、動(dòng)態(tài)綁定

基于動(dòng)態(tài)類(lèi)型,在某個(gè)實(shí)例對(duì)象被確定后,其類(lèi)型便被確定了。該對(duì)象對(duì)應(yīng)的屬性和響應(yīng)的消息也被完全確定,這就是動(dòng)態(tài)綁定。在繼續(xù)之前,需要明確 Objective-C中消息的概念。由于OC的動(dòng)態(tài)特性,在OC中其實(shí)很少提及“函數(shù)”的概念,傳統(tǒng)的函數(shù)一般在編譯時(shí)就已經(jīng)把參數(shù)信息和函數(shù)實(shí)現(xiàn)打包 到編譯后的源碼中了,而在OC中最常使用的是消息機(jī)制。調(diào)用一個(gè)實(shí)例的方法,所做的是向該實(shí)例的指針發(fā)送消息,實(shí)例在收到消息后,從自身的實(shí)現(xiàn)中尋找響應(yīng) 這條消息的方法。

動(dòng)態(tài)綁定所做的,即是在實(shí)例所屬類(lèi)確定后,將某些屬性和相應(yīng)的方法綁定到實(shí)例上。這里所指的屬性和方法當(dāng)然包括了原來(lái)沒(méi)有在類(lèi)中實(shí)現(xiàn)的,而是在運(yùn)行 時(shí)才需要的新加入的實(shí)現(xiàn)。在Cocoa層,我們一般向一個(gè)NSObject對(duì)象發(fā)送-respondsToSelector:或者 -instancesRespondToSelector:等來(lái)確定對(duì)象是否可以對(duì)某個(gè)SEL做出響應(yīng),而在OC消息轉(zhuǎn)發(fā)機(jī)制被觸發(fā)之前,對(duì)應(yīng)的類(lèi) 的+resolveClassMethod:和+resolveInstanceMethod:將會(huì)被調(diào)用,在此時(shí)有機(jī)會(huì)動(dòng)態(tài)地向類(lèi)或者實(shí)例添加新的方 法,也即類(lèi)的實(shí)現(xiàn)是可以動(dòng)態(tài)綁定的。一個(gè)例子:

  1. void dynamicMethodIMP(id self, SEL _cmd)   
  2.     // implementation .... 
  3.  
  4.  
  5.  
  6. //該方法在OC消息轉(zhuǎn)發(fā)生效前被調(diào)用 
  7. + (BOOL) resolveInstanceMethod:(SEL)aSEL 
  8. {  
  9.     if (aSEL == @selector(resolveThisMethodDynamically)) { 
  10.         //向[self class]中新加入返回為void的實(shí)現(xiàn),SEL名字為aSEL,實(shí)現(xiàn)的具體內(nèi)容為dynamicMethodIMP class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, “v@:”); 
  11.         return YES; 
  12.     } 
  13.     return [super resolveInstanceMethod:aSel]; 
  14. }   

當(dāng)然也可以在任意需要的地方調(diào)用class_addMethod或者method_setImplementation(前者添加實(shí)現(xiàn),后者替換實(shí)現(xiàn)),來(lái)完成動(dòng)態(tài)綁定的需求。

3、動(dòng)態(tài)加載

根據(jù)需求加載所需要的資源,這點(diǎn)很容易理解,對(duì)于iOS開(kāi)發(fā)來(lái)說(shuō),基本就是根據(jù)不同的機(jī)型做適配。最經(jīng)典的例子就是在Retina設(shè)備上加載@2x 的圖片,而在老一些的普通屏設(shè)備上加載原圖。隨著Retina iPad的推出,和之后可能的Retina Mac的出現(xiàn),這個(gè)特性相信會(huì)被越來(lái)越多地使用。

深入運(yùn)行時(shí)特性

基本的動(dòng)態(tài)特性在常規(guī)的Cocoa開(kāi)發(fā)中非常常用,特別是動(dòng)態(tài)類(lèi)型和動(dòng)態(tài)綁定。由于Cocoa程序大量地使用Protocol-Delegate的 設(shè)計(jì)模式,因此絕大部分的delegate指針類(lèi)型必須是id,以滿(mǎn)足運(yùn)行時(shí)delegate的動(dòng)態(tài)替換(在Java里這個(gè)設(shè)計(jì)模式被叫做 Strategy?不是很懂Java,求糾正)。而Objective-C還有一些高級(jí)或者說(shuō)更底層的運(yùn)行時(shí)特性,在一般的Cocoa開(kāi)發(fā)中較為少見(jiàn),基 本被運(yùn)用與編寫(xiě)OC和其他語(yǔ)言的接口上。但是如果有所了解并使用得當(dāng)?shù)脑?huà),在Cocoa開(kāi)發(fā)中往往可以輕易解決一些棘手問(wèn)題。

這類(lèi)運(yùn)行時(shí)特性大多由/usr/lib/libobjc.A.dylib這個(gè)動(dòng)態(tài)庫(kù)提供,里面包括了對(duì)于類(lèi)、實(shí)例成員、 成員方法和消息發(fā)送的很多API,包括獲取類(lèi)實(shí)例變量列表,替換類(lèi)中的方法,為類(lèi)成員添加變量,動(dòng)態(tài)改變方法實(shí)現(xiàn)等,十分強(qiáng)大。完整的API列表和手冊(cè)可 以在這里找到。雖然文檔開(kāi)頭表明是對(duì)于Mac OS X Objective-C 2.0適用,但是由于這些是OC的底層方法,因此對(duì)于iOS開(kāi)發(fā)來(lái)說(shuō)也是完全相同的。

一個(gè)簡(jiǎn)單的例子,比如在開(kāi)發(fā)Universal應(yīng)用或者游戲時(shí),如果使用IB構(gòu)建了大量的自定義的UI,那么在由iPhone版轉(zhuǎn)向iPad版的過(guò)程中所面臨的一個(gè)重要問(wèn)題就是如何從不同的nib中加載界面。在iOS5之前,所有的UIViewController在使用默認(rèn)的界面加載時(shí)(init或者initWithNibName:bundle:),都會(huì)走-loadNibNamed:owner:options:。而因?yàn)槲覀儫o(wú)法拿到-loadNibNamed:owner:options的實(shí)現(xiàn),因此對(duì)其重載是比較困難而且存在風(fēng)險(xiǎn)的。因此在做iPad版本的nib時(shí),一個(gè)簡(jiǎn)單的辦法是將所有的nib的命名方式統(tǒng)一,然后使用自己實(shí)現(xiàn)的新的類(lèi)似-loadNibNamed:owner:options的方法將原方法替換掉,同時(shí)保證非iPad的設(shè)備還走原來(lái)的loadNibNamed:owner:options方法。使用OC運(yùn)行時(shí)特性可以較簡(jiǎn)單地完成這一任務(wù)。

代碼如下,在程序運(yùn)行時(shí)調(diào)用+swizze,交換自己實(shí)現(xiàn)的loadPadNibNamed:owner:options和系統(tǒng)的loadNibNamed:owner:options,之后所有的loadNibNamed:owner:options消息都將會(huì)發(fā)為loadPadNibNamed:owner:options,由自己的代碼進(jìn)行處理。

  1. +(BOOL)swizze { 
  2.     Method oldMethod = class_getInstanceMethod(self, @selector(loadNibNamed:owner:options:)); 
  3.     if (!oldMethod) { 
  4.         return NO; 
  5.     } 
  6.     Method newMethod = class_getInstanceMethod(self, @selector(loadPadNibNamed:owner:options:)); 
  7.     if (!newMethod) { 
  8.         return NO; 
  9.     } 
  10.     method_exchangeImplementations(oldMethod, newMethod); 
  11.     return YES; 
  12. }   

loadPadNibNamed:owner:options的實(shí)現(xiàn)如下,注意在其中的loadPadNibNamed:owner:options由于之前已經(jīng)進(jìn)行了交換,因此實(shí)際會(huì)發(fā)送為系統(tǒng)的loadNibNamed:owner:options。以此完成了對(duì)不同資源的加載。

  1. -(NSArray *)loadPadNibNamed:(NSString *)name owner:(id)owner options:(NSDictionary *)options { 
  2.     NSString *newName = [name stringByReplacingOccurrencesOfString:@"@pad" withString:@""]; 
  3.     newName = [newName stringByAppendingFormat:@"@pad"]; 
  4.     //判斷是否存在 
  5.     NSFileManager *fm = [NSFileManager defaultManager]; 
  6.     NSString* filepath = [[NSBundle mainBundle] pathForResource:newName ofType:@”nib”]; 
  7.     //這里調(diào)用的loadPadNibNamed:owner:options:實(shí)際為為交換后的方法,即loadNibNamed:owner:options: 
  8.     if ([fm fileExistsAtPath:filepath]) { 
  9.         return [self loadPadNibNamed:newName owner:owner options:options]; 
  10.     } else { 
  11.         return [self loadPadNibNamed:name owner:owner options:options];  
  12.     } 
  13. }   

當(dāng)然這只是一個(gè)簡(jiǎn)單的例子,而且這個(gè)功能也可以通過(guò)別的方法來(lái)實(shí)現(xiàn)。比如添加UIViewController的類(lèi)別來(lái)重載init,但是這樣的重載會(huì)比 較危險(xiǎn),因?yàn)槟鉛IViewController的實(shí)現(xiàn)你無(wú)法完全知道,因此可能會(huì)由于重載導(dǎo)致某些本來(lái)應(yīng)有的init代碼沒(méi)有覆蓋,從而出現(xiàn)不可預(yù)測(cè)的 錯(cuò)誤。當(dāng)然在上面這個(gè)例子中重載VC的init的話(huà)沒(méi)有什么問(wèn)題(因?yàn)閷?duì)于VC,init的方法會(huì)被自動(dòng)轉(zhuǎn)發(fā)為 loadNibNamed:owner:options,因此init方法并沒(méi)有做其他更復(fù)雜的事情,因此只要初始化VC時(shí)使用的都是init的話(huà)就沒(méi)有 問(wèn)題)。但是并不能保證這樣的重載對(duì)于其他類(lèi)也是可行的。因此對(duì)于實(shí)現(xiàn)未知的系統(tǒng)方法,使用上面的運(yùn)行時(shí)交換方法會(huì)是一個(gè)不錯(cuò)的選擇~

原文地址:http://onevcat.com/2012/04/objective-c-runtime/

責(zé)任編輯:閆佳明 來(lái)源: onevcat.com
相關(guān)推薦

2014-11-25 10:18:17

Objective-C

2013-07-24 19:19:03

Objective-CiOS開(kāi)發(fā)動(dòng)態(tài)特性之protoc

2011-05-11 11:20:26

Objective-C

2011-08-04 10:57:33

Objective-C C語(yǔ)言 BOOL

2011-05-11 14:06:49

Objective-C

2011-08-04 14:58:37

Objective-C Cocoa NSString

2013-08-21 14:57:42

objective-c問(wèn)題

2015-11-02 10:13:41

iOSObjective-C語(yǔ)法

2014-04-28 09:56:56

Objective-CiOS命名空間

2011-07-25 10:03:06

Objective-C 委托

2011-08-05 14:03:39

Objective-C 對(duì)象 模板

2011-08-18 09:21:17

Objective-C

2014-12-12 14:57:11

Objective-C類(lèi)封裝

2010-11-24 10:35:40

Objective-C

2014-04-15 11:27:50

C++開(kāi)發(fā)者Objective-C核心語(yǔ)法

2011-07-25 10:30:41

Objective-C Xcode 重構(gòu)

2011-07-25 11:02:29

Objective-C Xcode 標(biāo)簽

2011-07-25 10:14:13

Objective-C Xcode

2011-08-04 13:55:10

Cocoa Objective- 文件

2011-08-15 17:06:01

Objective-CNSLog
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产99精品 | 亚洲一区成人 | 欧美亚洲国产精品 | 福利久久 | 久久精品视频网站 | 国产精品亚洲精品久久 | 黄色av大片| 羞羞视频网站免费看 | 国产精品无码久久久久 | 中文字幕精品一区二区三区精品 | 国产亚洲欧美另类一区二区三区 | 一区二区三区亚洲 | 欧美视频中文字幕 | 一区二区三区中文字幕 | 日韩网站免费观看 | 亚洲福利一区二区 | 亚洲视频免费在线看 | 91成人在线| 久久婷婷国产麻豆91 | 国内自拍偷拍视频 | 一级片av | 久久av一区二区三区 | 日韩亚洲欧美一区 | 亚洲午夜av久久乱码 | 日本免费在线 | 久久精品视频免费看 | 99影视 | 欧美激情综合 | 天天操天天射综合 | 欧美日韩不卡 | 久久成人免费 | 中文字幕 欧美 日韩 | 日韩在线看片 | 久久精品欧美一区二区三区不卡 | 国产特级毛片aaaaaa | 国产福利91精品一区二区三区 | 欧美一区二区三区在线看 | 九九热在线免费观看 | xxx.在线观看 | 成在线人视频免费视频 | 国产精品久久久久久久岛一牛影视 |