ios - ObjC : +[NSObject isSubclassOfClass:] gives incorrect failure

标签 ios objective-c

  • 我有一个 iOS 静态库,它定义了一个 NSOperation 基类,客户端应该将其子类化以将他们自己的逻辑添加到:@interface BaseClass : NSOperation/p>

  • 客户端向管理器注册它们的子类:-[OperationManagerClass registerClass:forType:]

  • 在管理器中,我想强制要求您必须注册 BaseClass 的子类,而不仅仅是 NSOperation

好吧,似乎断言 +isSubclassOfClass: 应该可以完成工作。但是……事实并非如此。

@implementation OperationManagerClass

- (void)registerClass:(Class)aClass forType:(NSString *)type
{
    NSAssert([aClass isSubclassOfClass:[BaseClass class]);

    self.registeredClasses[type] = aClass;
}

@end

断言总是NO,即使传递给BaseClass

在类(class)层次结构中走得更高怎么样? NSOperationNSObject 都响应 YES!

(lldb) p (BOOL)[aClass isSubclassOfClass:[BaseClass class]]
(BOOL) $0 = NO
(lldb) po aClass
BaseClass
(lldb) p (BOOL)[aClass isSubclassOfClass:[NSOperation class]]
(BOOL) $2 = YES
(lldb) p (BOOL)[aClass isSubclassOfClass:[NSObject class]]
(BOOL) $3 = YES

请注意,基本操作类的使用者是 iOS 应用程序项目中的子类,OperationManagerClassBaseClass 位于包含的静态库中。为什么我认为这可能与 isSubclassOfClass: 错误有关?由于以下...

仍在 libSharedStuff.a 中

@implementation OperationManagerClass

- (void)registerClass:(Class)aClass forType:(NSString *)type
{
    // Obviously OperationManagerClass.m cannot #import "OutsideClass.h"
    NSAssert([aClass isSubclassOfClass:NSClassFromString(@"OutsideClass");

    self.registeredClasses[type] = aClass;
}

@end

在应用目标中

@interface OutsideClass : NSOperation
@end

@interface OutsideClassSubA : OutsideClass
@end

... 传入 OutsideClassSubA 时产生以下结果:

(lldb) p (BOOL)[aClass isSubclassOfClass:[OutsideClass class]]
(BOOL) $0 = YES
(lldb) po aClass
OutsideClassSubA
(lldb) p (BOOL)[aClass isSubclassOfClass:[NSOperation class]]
(BOOL) $2 = YES
(lldb) p (BOOL)[aClass isSubclassOfClass:[NSObject class]]
(BOOL) $3 = YES

这是怎么回事?为什么 +isSubclassOfClass: 给出了错误的答案?如何强制 aClass 参数必须是我的 BaseClass 的子类?


编辑:
我意识到我发布的示例在将这些部分拉入单独的 Xcode 工作区后工作正常。我有 posted the toy source code from above我省略了原来的描述。

我实际上有两个静态库(libSharedStuff.alibHelperSharedStuff.a)。应用程序目标链接到 libSharedStuff.a,单元测试目标取决于应用程序目标以及链接 libHelperSharedStuff.a。当 BaseClass.m两个 静态库目标的成员时,+isSubclassOfClass: 将在单元测试断言中失败。具体来说,当我通过 MockBaseClass 时失败,它是 BaseClass 的子类,是单元测试目标的一部分。

所有这些都在上面链接的项目中进行了说明。

最佳答案

正如我在编辑问题时所解释的,我在两个静态库 libSharedStuff.alibHelperSharedStuff.aBaseClass.m。主要应用程序目标链接到 libSharedStuff.a,单元测试目标链接到 libHelperSharedStuff.a。这意味着当 .xctest 包在运行时被注入(inject)我的应用程序时,BaseClass 符号被定义了两次

(也许?这可能吗?运行时实际发生了什么?)。

我似乎在我的单元测试目标中 MockSubclassOfBaseClass 继承自 libHelperSharedStuff.a 中的 BaseClass 符号,而在我的应用程序目标中 SubclassOfBaseClass继承自libSharedStuff.a中的BaseClass符号。如果是这样,那么当传入 MockSubclassOfBaseClass 时,+isSublcassOfClass: 响应 NO 的原因就有意义了!

非常感谢任何澄清、确认或提供我的正确想法的更好见解的答案。

关于ios - ObjC : +[NSObject isSubclassOfClass:] gives incorrect failure,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19883472/

相关文章:

ios - 缩放 CALayer 会使 View 变得模糊

ios - UIAlertController 无法满足约束

ios - MOGenerator 和 NSOrderedSet

ios - 如何将 UILabel 高度设置为零

ios - 错误 : Error installing cocoapods: ERROR: Failed to build gem native extension

objective-c - AVCaptureSession预设照片和AVCaptureVideoPreviewLayer大小

ios - 我无法从 JSON 获取我的数组以加载到 UITableView

iphone - 如何从 NSNotification 对象获取数据?

ios - 如何调整自定义 UITableViewCell nib 文件的大小以适应 tableView?

ios - Game Center 回合制游戏