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

我可以从调试器中的两种类型中收集到的所有其他内容都是相同的。我什至可以比较 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 文件包含在测试目标编译源中。删除后,它开始按预期运行。感谢这篇文章帮助我解决了这个问题。

4

2 回答 2

2

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


@interface BaseClass

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


@interface BaseClass : NSObject

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

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

您的class c初始化应该可以正常工作。

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

于 2013-01-23T02:45:16.587 回答
2

我在我的测试应用程序中添加了您的代码。我不得不更改这两个instance变量的名称,之后编译器给了我一个警告(“找不到类方法'+alloc'”),当我运行它时程序崩溃了。

然后我改变了这一行:

@interface BaseClass : NSObject

即我BaseClassNSObject. 不再有编译器警告,代码按预期运行,即第二个isKindOfClass返回 YES。

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

于 2013-01-23T02:30:51.013 回答