自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深度解析iPhone內(nèi)省機(jī)制

移動開發(fā) iOS
本文主要介紹的是iPhone內(nèi)省機(jī)制,從評估繼承關(guān)系、方法實現(xiàn)和協(xié)議遵循、對象的比較等方面來詳細(xì)的學(xué)習(xí)iPhone內(nèi)省機(jī)制。

iPhone內(nèi)省機(jī)制是本文要介紹的內(nèi)容,從評估繼承關(guān)系、方法實現(xiàn)和協(xié)議遵循、對象的比較等方面來詳細(xì)的學(xué)習(xí)iPhone內(nèi)省機(jī)制,我們先來看詳細(xì)內(nèi)容。

內(nèi)省(Introspection)是面向?qū)ο笳Z言和環(huán)境的一個強(qiáng)大特性,Objective-C和Cocoa在這個方面尤其的豐富。內(nèi)省是對象揭示自己作為一個運(yùn)行時對象的詳細(xì)信息的一種能力。這些詳細(xì)信息包括對象在繼承樹上的位置,對象是否遵循特定的協(xié)議,以及是否可以響應(yīng)特定的消息。NSObject協(xié)議和類定義了很多內(nèi)省方法,用于查詢運(yùn)行時信息,以便根據(jù)對象的特征進(jìn)行識別。

明智地使用內(nèi)省可以使面向?qū)ο蟮某绦蚋痈咝Ш蛷?qiáng)壯。它有助于避免錯誤地進(jìn)行消息派發(fā)、錯誤地假設(shè)對象相等、以及類似的問題。下面的部分將介紹如何在代碼中有效地使用NSObject的內(nèi)省方法。

評估繼承關(guān)系

一旦您知道一個對象屬于什么類,就可能已經(jīng)相當(dāng)了解這個對象了。您可以知道它具有什么能力、哪些屬性、以及可以響應(yīng)哪些消息。即使在內(nèi)省之后不能了解對象所屬的類,也可以知道該對象不能響應(yīng)特定的消息。

NSObject協(xié)議聲明了幾個方法,用于確定對象在類層次中的位置。這些方法在不同粒度上進(jìn)行操作,比如class和superclass實例方法分別返回代表類和超類的Class對象。使用這些方法需要將一個Class對象和另一個進(jìn)行對比。列表2-7給出了一個簡單(可能是沒有價值)的用法實例。

使用類和超類的方法

  1. // ...  
  2. while ( id anObject = [objectEnumerator nextObject] ) {  
  3.  if ( [self class] == [anObject superclass] ) {  
  4.  // do something appropriate...  
  5.  }  

請注意:有些時候您需要通過class或superclass方法得到正確的類消息接收者。

更加常見的是檢查對象類的從屬關(guān)系,這種情況下您需要向該對象發(fā)送isKindOfClass:或isMemberOfClass:消息。前一個方法返回接收者是否為給定類或其繼承類的實例,isMemberOfClass:消息則告訴您接收者是否為指定類的實例。isKindOfClass: 方法通常更有用,因為通過它可以知道是否可以向該對象發(fā)送一系列消息。考慮列表2-8中的代碼片斷:

使用isKindOfClass:方法

  1. if ([item isKindOfClass:[NSData class]]) {  
  2.  const unsigned char *bytes = [item bytes];  
  3.  unsigned int length = [item length];  
  4.  // ...  

確定tem對象是NSData類的繼承類的實例之后,代碼就知道可以向它發(fā)送NSData的bytes和length消息。假定item是NSMutableData類的一個實例,則isKindOfClass:和isMemberOfClass:之間的差別就變得更加明顯。如果您調(diào)用的是isMemberOfClass:,而不是isKindOfClass:,條件控制塊中的代碼將永遠(yuǎn)不會被執(zhí)行,因為item并不是NSData類的實例,而是其子類NSMutableData的實例。

方法實現(xiàn)和協(xié)議遵循

NSObject還有兩個功能更加強(qiáng)大的內(nèi)省方法,即respondsToSelector:和conformsToProtocol:。這兩個方法分別告訴您一個對象是否實現(xiàn)特定的方法,以及是否遵循指定的正式協(xié)議(即該對象是否采納了該協(xié)議,且實現(xiàn)了該協(xié)議的所有方法)。

在代碼中,您可以在類似的情況下使用這些方法。通過這些方法,您可以在將消息或消息集合發(fā)送給某些潛在的匿名對象之前,確定它們是否可以正確地進(jìn)行響應(yīng)。在發(fā)送消息之前進(jìn)行檢查可以避免由不能識別的選擇器引起的運(yùn)行時例外。

在實現(xiàn)非正式協(xié)議(這種協(xié)議是委托技術(shù)的基礎(chǔ))時,Application Kit就是在調(diào)用委托方法之前檢查委托對象是否實現(xiàn)該方法(通過respondsToSelector:方法)。

顯示了如何在代碼中使用respondsToSelector:方法。

使用respondsToSelector:方法

  1. - (void)doCommandBySelector:(SEL)aSelector {  
  2.  if ([self respondsToSelector:aSelector]) {  
  3.  [self performSelector:aSelector withObject:nil];  
  4.  } else {  
  5.  [_client doCommandBySelector:aSelector];  
  6.  }  

顯示如何在代碼中使用conformsToProtocol:方法:

使用conformsToProtocol:方法

  1. // ...  
  2. if (!([((id)testObject) conformsToProtocol:@protocol(NSMenuItem)])) {  
  3.  NSLog(@"Custom MenuItem, '%@', not loaded; it must conform to the  
  4.  'NSMenuItem' protocol.\n", [testObject class]);  
  5.  [testObject release];  
  6.  testObject = nil;  

對象的比較

hash和isEqual:方法雖然不是嚴(yán)格的內(nèi)省方法,但是可以發(fā)揮類似的作用,是進(jìn)行對象的識別和比較時不可或缺的運(yùn)行時工具。它們并不向運(yùn)行環(huán)境查詢對象信息,而是依賴于具體類的比較邏輯。

hash和isEqual:方法都在NSObject協(xié)議中聲明,且彼此關(guān)系緊密。實現(xiàn)hash方法必須返回一個整型數(shù),作為哈希表結(jié)構(gòu)中的表地址。兩個對象相等(isEqual:方法的判斷結(jié)果)意味著它們有相同的哈希值。如果您的對象可能被包含在象NSSet這樣的集合中,則需要定義hash方法,并確保該方法在兩個對象相等的時候返回相同的哈希值。NSObject類中缺省的isEqual:實現(xiàn)只是簡單地檢查指針是否相等。

isEqual:的使用相當(dāng)直接,它將消息的接收者和通過參數(shù)傳入的對象進(jìn)行比較。對象的比較常??梢栽谶\(yùn)行時決定應(yīng)該對對象做些什么。如列表2-11所示,您可以通過isEqual:來確定是否執(zhí)行某一個動作。在這個例子中,動作是指保存被修改了的預(yù)置信息。

使用isEqual:方法

  1. - (void)saveDefaults {  
  2.  NSDictionary *prefs = [self preferences];  
  3.  if (![origValues isEqual:prefs])  
  4.  [Preferences savePreferencesToDefaults:prefs];  

如果您正在創(chuàng)建子類,則可能需要重載isEqual:方法,以進(jìn)一步檢查對象是否相等。子類可能定義額外的屬性,當(dāng)兩個實例被認(rèn)為相等時,屬性的值必須相同。舉例來說,假定您創(chuàng)建一個名為MyWidget的NSObject子類,類中包含兩個實例變量:name和data。當(dāng)MyWidget的兩個實例被認(rèn)為是相等時,這些變量必須具有相同的值。列表2-12顯示如何在MyWidget類中實現(xiàn)isEqual:方法。

重載isEqual:方法

  1. - (BOOL)isEqual:(id)other {  
  2.  if (other == self)   
  3.  return YES;  
  4.  if (!other || ![other isKindOfClass:[self class]])  
  5.  return NO;  
  6.  return [self isEqualToWidget:other];  
  7. }  
  8.  
  9. - (BOOL)isEqualToWidget:(MyWidget *)aWidget {  
  10.  if (self == aWidget)  
  11.  return YES;  
  12.  if (![(id)[self name] isEqual:[aWidget name]])  
  13.  return NO;  
  14.  if (![[self data] isEqualToData:[aWidget data]])  
  15.  return NO;  
  16.  return YES;  

isEqual:方法首先檢查指針的等同性,然后是類的等同性,最后調(diào)用對象的比較器進(jìn)行比較。比較器的名稱指示出參與比較的對象的類名稱。這種類型的比較器對傳入的對象進(jìn)行強(qiáng)制類型檢查,是Cocoa中常見的約定,NSString的isEqualToString:和NSTimeZone的isEqualToTimeZone:就是兩個這樣的例子。特定類的比較器(在這個例子中是isEqualToWidget:)負(fù)責(zé)執(zhí)行name和data變量的等同性。

Cocoa框架的所有isEqualToType:方法中,nil都不是正當(dāng)?shù)膮?shù),這些方法的實現(xiàn)在接收到nil參數(shù)時會拋出例外。然而為了向后兼容,Cocoa框架中的isEqual:方法可以接收nil值,在這種情況下返回NO。

小結(jié):深度解析iPhone內(nèi)省機(jī)制的內(nèi)容介紹完了,希望本文對你有所幫助!

責(zé)任編輯:zhaolei 來源: 博客園
相關(guān)推薦

2011-07-01 15:04:49

Qt 內(nèi)省

2011-07-29 15:09:48

iPhone Category

2011-07-18 14:23:40

iPhone 多任務(wù)

2011-08-12 11:23:47

iPhone窗口視圖

2010-11-25 09:37:14

MySQL查詢緩存機(jī)制

2016-10-09 14:41:40

Swift開發(fā)ARC

2011-06-22 16:50:09

Qt 進(jìn)程 通信機(jī)制

2011-06-07 17:16:47

iPhone 數(shù)據(jù)

2011-08-19 13:45:14

iPhone應(yīng)用iPhone OS數(shù)據(jù)

2011-08-12 14:54:45

iPhone委托

2011-07-27 17:02:12

Xcode iPhone 單元測試

2024-12-20 16:46:22

Spring三級緩存

2011-07-29 14:55:25

iPhone開發(fā) 動畫過渡

2011-02-28 09:51:43

內(nèi)省

2011-08-11 17:00:33

iPhone數(shù)據(jù)庫SQLite

2011-07-26 14:07:29

iPhone 二維碼

2009-07-14 18:09:08

Jython的內(nèi)省

2010-11-12 10:53:28

微軟Azure

2024-10-12 12:55:26

2011-06-02 17:27:49

iphone 多線程
點贊
收藏

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