7

インスタンスの作成方法に応じて 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

デバッガーで 2 つの型から収集できる他のすべては同じです。NSStringFromClass([instance superclass]) の両方の結果を比較することもでき、それらは等しいです。

私は単純なものが欠けているに違いありません。

更新されたコード

これは単体テスト コードです。

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 を返します。簡単な例を作成しようとしました (ベースまたは派生に ivar はありません)。テストでは失敗しますが、標準のランタイムでは動作します。

これがテスト時にのみ問題になる理由はありますか? テスト ターゲットに何か不足がありますか?

解決済み

テスト ターゲットのコンパイル ソースに .m ファイルを含めました。削除すると、これは期待どおりに動作し始めました。これを解決するのを手伝ってくれたこの投稿に感謝します。

4

2 に答える 2

2

BaseClassを継承するかどうかNSObjectによって、このコードの結果が変わります。次の 2 つの可能性があります。


@interface BaseClass

から継承BaseClass せずに定義した場合NSObject、率直に言って、コンパイラがinstance変数の設定を回避できることに驚いています。+alloc独自のメソッドと-initメソッドを定義しない限りBaseClass(これは可能です)、テストの最初の行はまったく機能しません。適切な+allocand-initメソッドを定義した場合でも、-isKindOfClass:それも自分で定義する必要があるため、問題が発生します。したがって、基本的にこれは機能しません。次のオプションを見てみましょう...


@interface BaseClass : NSObject

テストの最初の行 (作成中instance) は正常に動作するはずです。

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

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

最終行は投稿したコードで返されるはずなので、ここで省略されているものがあると思います(から継承するとYES仮定します)...最終行は を返す必要があります。何が起こったのかは、誤った初期化/入力ミス/その他によって何らかの形で含まれていると思われます。この場合、メッセージを送信すると が返されるため、送信すると が返されます。BaseClassNSObjectYESinstancenilnil-isKindOfClassNO

于 2013-01-23T02:45:16.587 に答える
2

私のテストアプリにあなたのコードを追加しました。2 つの変数の名前を変更する必要がありましたinstance。その後、コンパイラから警告 (「クラス メソッド '+alloc' が見つかりません」) が表示され、実行するとプログラムがクラッシュしました。

次に、この行を変更しました:

@interface BaseClass : NSObject

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

NSObject欠落が問題の原因であるかどうかはわかりません。そうでない場合は、他の誰かが介入する必要があります。そうであれば、どうやってコードを実行できたのだろうか。

于 2013-01-23T02:30:51.013 に答える