2013-01-23 7 views
7

誰かが、isKindOfClassがインスタンスの作成方法によって異なる結果を返す理由を説明できますか?isKindOfClass Behavior

@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 

デバッガの2つのタイプから収集できるものはすべて同じです。私は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

試したところ、2件あります。 'instance'のクラスを試してみてください。 –

+0

これは' BaseClass:NSObject'になっていますか?その質問に対する答えはあなたの質問に対する答えを変えます。 – Ephemera

+1

実際のコードを貼り付ける必要があります。サンプルコードは、 'BaseClass'を' NSObject'のサブクラスにしている限り、うまく動作します(別の方法でもコンパイルされません)。 –

答えて

2

私のテストアプリケーションに自分のコードを追加しました。私は2つのinstance変数の名前を変更しなければなりません。その後、コンパイラは私に警告を出しました( "クラスメソッド '+ alloc' not found")、プログラムを実行するとクラッシュしました。

私は、この行を変更:

@interface BaseClass : NSObject 

すなわちIはNSObjectからBaseClass由来。コンパイラの警告がなくなり、コードが期待どおりに実行されます。つまり、2番目のisKindOfClassはYESを返します。

不足しているNSObjectが原因であるかどうかわかりません。そうでなければ、他の人がステップインする必要があります。もしそうなら、どのようにコードを実行することができたのだろうか。

2

BaseClassNSObjectから継承するかどうかによって、このコードの結果が変更されます。あなたは率直に言って、私は、コンパイラはあなたのinstance変数を設定すると離れて取得してみましょう驚いて、NSObjectから継承なしBaseClassを定義した場合


@interface BaseClass 

:ここでは二つの可能性があります。 +alloc-initのメソッドをBaseClass(これが可能です)に定義していない限り、テストの最初の行はまったく機能しません。適切な+alloc-initメソッドを定義した場合は、-isKindOfClass:に問題が発生します。自分自身で定義する必要があります。 だから基本的にこれはあなたのテスト(instanceを作成する)の最初の行が正常に動作する必要があり


@interface BaseClass : NSObject 

...のは、次のオプションを見てみましょう、動作しません。

[instance isKindOfClass:[BaseClass class]]は、適切な値YESを返します。

class cの初期化が正しく機能するはずです。

私は最後の行は、あなたが投稿したコード(NSObjectからBaseClass継承を想定)でYESを返す必要があります...最後の行はYESを返す必要がありますので、ここでは省略何かがあると思います。私は何が起こったのかもしれないと思われますinstanceは何らかの形で間違った初期化/タイプミスなどを通してnilを含んでいます。この場合、メッセージを送信すると、nilが返され、-isKindOfClassを送信するとNOが返されます。