有人可以解释为什么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帮助我解决此问题。
答案 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
上定义了自己的-init
和BaseClass
方法(这是可能的),否则测试的第一行根本不起作用。如果您确实定义了适当的+alloc
和-init
方法,那么您仍然会遇到-isKindOfClass:
的问题,因为您还需要自己定义它。
所以基本上这不起作用,让我们看看下一个选项......
@interface BaseClass : NSObject
测试的第一行(创建instance
)应该可以正常工作。
[instance isKindOfClass:[BaseClass class]]
会返回适当的值YES
。
您的class c
初始化应该可以正常运行。
我怀疑这里省略了一些东西,因为最后一行应该返回YES
和你发布的代码(假设BaseClass
继承自NSObject
)...最后一行应该返回{ {1}}。我怀疑可能发生的事情是YES
通过错误的初始化/拼写错误/等等以某种方式结束了instance
。在这种情况下,向其发送消息只会返回nil
,因此发送nil
将会产生-isKindOfClass
。