【问题标题】:isKindOfClass BehaviorisKindOfClass 行为
【发布时间】:2013-01-23 01:51:36
【问题描述】:

有人可以解释为什么 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 帮助我解决了这个问题。

【问题讨论】:

  • 刚试过,得到两个YES。尝试打印instance的类
  • 应该是BaseClass : NSObject 吗?该问题的答案将改变您的问题的答案。
  • 你需要粘贴你的真实代码。只要我将BaseClass 设为NSObject 的子类,您的示例代码就可以正常工作(否则它甚至不会编译)。
  • @xlc0212 尝试作为单元测试运行。

标签: objective-c


【解决方案1】:

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

然后我改变了这一行:

@interface BaseClass : NSObject

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

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

【讨论】:

    【解决方案2】:

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


    @interface BaseClass
    

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


    @interface BaseClass : NSObject
    

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

    [instance isKindOfClass:[BaseClass class]] 返回相应的值,YES

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-28
      • 2017-02-09
      相关资源
      最近更新 更多