isKindOfClass行为

时间:2013-01-23 01:51:36

标签: objective-c

有人可以解释为什么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([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。我甚至试图创建一个简化的示例(没有基础或衍生的ivars),它在测试中失败但在标准运行时工作。

为什么这可能只是测试时的问题?我的测试目标是否遗漏了什么?

解决

我已将.m文件包含在测试目标编译源中。一旦删除,这开始按预期运行。感谢this post帮助我解决此问题。

2 个答案:

答案 0 :(得分:2)

我在我的测试应用中添加了您的代码。我不得不更改两个instance变量的名称,之后编译器给了我一个警告(“Class method'+ alloc'not found'),程序在我运行时崩溃了。

然后我改变了这一行:

@interface BaseClass : NSObject

即。我从BaseClass派生了NSObject。不再有编译器警告,代码按预期运行,即第二个isKindOfClass返回YES。

我不知道遗失的NSObject是否会导致您的问题。如果不是那么其他人必须介入。如果是,我想知道你是如何运行你的代码的。

答案 1 :(得分:2)

BaseClass是否继承自NSObject会改变此代码的结果。以下是两种可能性:


@interface BaseClass

如果您已定义BaseClass 继承自NSObject,那么坦率地说,令我感到惊讶的是编译器可让您轻松设置instance变量。 除非您在+alloc上定义了自己的-initBaseClass方法(这是可能的),否则测试的第一行根本不起作用。如果您确实定义了适当的+alloc-init方法,那么您仍然会遇到-isKindOfClass:的问题,因为您还需要自己定义它。 所以基本上这不起作用,让我们看看下一个选项......


@interface BaseClass : NSObject

测试的第一行(创建instance)应该可以正常工作。

[instance isKindOfClass:[BaseClass class]]会返回适当的值YES

您的class c初始化应该可以正常运行。

我怀疑这里省略了一些东西,因为最后一行应该返回YES和你发布的代码(假设BaseClass继承自NSObject)...最后一行应该返回{ {1}}。我怀疑可能发生的事情是YES通过错误的初始化/拼写错误/等等以某种方式结束了instance。在这种情况下,向其发送消息只会返回nil,因此发送nil将会产生-isKindOfClass