2013-01-23 61 views
7

有人可以解釋爲什麼isKindOfClass根據實例的創建方式返回不同的結果嗎?isKindOfClass行爲

@interface BaseClass 
... 

@interface DerivedClassA : BaseClass 
... 

DerivedClassA *instance = [[DerivedClassA alloc] init]; 

[instance isKindOfClass:[BaseClass class]]; // yields YES 

Class c = NSClassFromString(@"DerivedClassA"); 
id instance = [[c alloc] init]; 

[instance isKindOfClass:[BaseClass class]]; // yields NO 

我可以從調試器中的兩種類型中收集的其他東西都是相同的。我甚至可以比較NSStringFromClass([實例超類])的結果和它們相等。

我必須缺少一些簡單的東西。

更新的代碼

這是單元測試代碼。

LightingUnit *u1 = [[LightingUnit alloc] init]; 

STAssertTrue([u1 isKindOfClass:[ModelBase class]], @"should be derived from base"); 

Class uc = NSClassFromString(@"LightingUnit"); 
id u2 = [[uc alloc] init]; 

STAssertTrue([u2 isKindOfClass:[ModelBase class]], @"should be derived from base"); 

這裏是類定義。

@interface ModelBase : NSObject 

@property (readonly) NSString *__type; 

- (id)initWithDictionary:(NSDictionary *)dictionary; 

- (NSMutableDictionary *)dictionary; 

@end 

@interface LightingUnit : ModelBase 

@property (strong, nonatomic) NSString *name; 
@property NSInteger unitId; 

@end 

可能的答案

當我在測試環境中的作品外運行這個邏輯沒有問題。顯然唯一的區別是刪除STAssertTrue語句並將其替換爲我的條件。在這種情況下,他們都返回YES。我甚至嘗試創建一個簡化的示例(無基礎或派生ivars),它在測試中失敗,但在標準運行時工作。

任何想法,爲什麼這可能只是一個問題,當測試?我的測試目標是否缺少某些東西

解決

我已經包含在測試目標編譯源代碼的.m文件。一旦刪除,開始按預期行事。感謝this post幫助我解決這個問題。

+0

剛試過,得到兩個YES。嘗試打印'實例'類 –

+0

是否應該是'BaseClass:NSObject'?這個問題的答案將改變你的問題的答案。 – Ephemera

+1

你需要粘貼你的真實代碼。你的示例代碼工作得很好,只要我把'BaseClass'作爲'NSObject'的一個子類(它甚至不會編譯)。 –

回答

2

我在您的測試應用程序中添加了您的代碼。我必須更改兩個instance變量的名稱,之後編譯器給了我一個警告(「Class method'+ alloc'not found」),並且程序在運行時崩潰了。

我然後改變這一行:

@interface BaseClass : NSObject 

即我衍生BaseClassNSObject。沒有更多的編譯器警告,代碼按預期運行,即第二個isKindOfClass返回YES。

我不知道是否缺少NSObject是什麼原因導致您的問題。如果不是,那麼其他人必須介入。如果是,我想知道你是如何運行你的代碼的。

2

BaseClass是否繼承自NSObject將改變此代碼的結果。這裏有兩種可能性:


@interface BaseClass 

如果定義BaseClassNSObject繼承,那麼很坦率地說我很驚訝,編譯器讓您設置您的instance變量脫身。 除非您在BaseClass(這是可能的)上定義了自己的+alloc-init方法,否則測試的第一行根本不起作用。如果您確定了合適的+alloc-init方法,您仍然會遇到-isKindOfClass:問題,因爲您還需要自己定義。 所以基本上這是不行的,讓我們來看看下一個選項...


@interface BaseClass : NSObject 

測試的第一行(創建instance)應該工作的罰款。

[instance isKindOfClass:[BaseClass class]]返回相應的值YES

您的class c初始化應該正常工作。

我懷疑有此省略,因爲最後一行應該與您發佈的代碼(假設BaseClass繼承NSObject)返回YES東西......最後一行應該返回YES。我懷疑可能發生的事情是instance由於不正確的初始化/打字錯誤/等原因而不知何故結束了nil。在這種情況下,發送消息只會返回nil,因此發送-isKindOfClass將產生NO

相關問題