【问题标题】:isKindOfClass doesn't work as expectedisKindOfClass 没有按预期工作
【发布时间】:2012-09-12 10:30:25
【问题描述】:

我正在开发一个 iOS5+ 项目(xcode 4.4.1 SDK 5.1)

我在单元测试中有这段代码:

[_appDelegate application:nil didFinishLaunchingWithOptions:nil];

UITabBarController *tabBarController = (UITabBarController*)_appDelegate.window.rootViewController;

NSArray *viewControllers = [tabBarController viewControllers];

UINavigationController *nc_1 = [viewControllers objectAtIndex:0];
UIViewController *vc_1 = nc_1.topViewController;

STAssertTrue([vc_1 isKindOfClass:[ScheduleViewController class]]==YES, @"UITabBarController first tab should be a ScheduleViewController class");

如果我运行测试,测试失败。

所以我用调试器检查:

(lldb) po [ScheduleViewController class]
(id) $1 = 0x00142b04 ScheduleViewController
(lldb) po vc_1
(UIViewController *) $2 = 0x11a32dc0 <ScheduleViewController: 0x11a32dc0>
(lldb) print (BOOL) [vc_1 isKindOfClass:(Class)[ScheduleViewController class]]
(BOOL) $4 = YES
(lldb) po [vc_1 class]
(id) $5 = 0x00142b04 ScheduleViewController
(lldb) 

在应用程序中:didFinishLaunchingWithOptions:我创建了一个 ScheduleViewController 并将其用作导航控制器的 rootController。调试器说它是正确的。 我不明白上面的断言有什么问题。

有人知道这个吗?

更新

断言的第一个实现是:

STAssertTrue([vc_1 isKindOfClass:[ScheduleViewController class]], @"UITabBarController first tab should be a ScheduleViewController class");

断言同样失败。

更新 2

正如评论中所建议的,我尝试在断言之前添加这段代码:

BOOL vcBool = [vc_1 isKindOfClass:[ScheduleViewController class]];

使用我看到的调试器:

(lldb) print (BOOL) [vc_1 isKindOfClass:(Class)[ScheduleViewController class]]
(BOOL) $1 = YES
(lldb) print (BOOL) vcBool
(BOOL) $2 = NO
(lldb) 

更新 3

按照 cmets 中的建议,我在断言之前添加了这一行:

NSLog(@"vc_1=%@ class=%@", vc_1, NSStringFromClass([vc_1 class]));

从调试控制台:

vc_1=<ScheduleViewController: 0x993bdb0> class=ScheduleViewController

【问题讨论】:

  • 您是否尝试删除==YES
  • @dasdom == YES 是不必要的,但它对功能有影响吗?
  • 你确定它在 STAssertTrue() 声明中失败了,而不是在其他地方?
  • 如果你在失败的测试上面添加这一行,我敢打赌它也会失败。您的代码很可能遗漏了 OCUnit 的某些初始化步骤:'STAssertTrue(YES, @"Even YES failed");'如果奇迹发生,则从 STAssert 中提取您的语句并将值分配给布尔值,记录它,然后在 BOOL 上进行 STAssert。
  • 所以在 'BOOL vcBool' 之前做更多的日志记录: NSLog(@"vc_1=%@ class=%@", vc_1, NSStringFromClass([vc_1 class]));'我猜 vc_1 是 nil,但是当你到达调试器时,它已经设置好了。

标签: objective-c ios xcode llvm nsobject


【解决方案1】:

我找到了解决办法。

这与 cmets 中 @vacawama 链接的帖子中提出的解决方案相反。我在测试目标中也有应用程序目标的所有 *.m 源。当我在寻找 isKindOfClass 问题的解决方案时,我注意到在测试会话开始时控制台上有很多警告。警告是这样的:

Class AClass is implemented in both /Application Support/iPhone Simulator/5.0/Applications/7FC68A9C-4F2C-4A30-85AD-87D8ABA7A275/App.app/App and /Developer/Xcode/DerivedData/App-fvbgaqbdupuoodgquxhlwbudpsin/Build/Products/Debug-iphonesimulator/App.octest/AppTests. One of the two will be used. Which one is undefined.

我从测试目标中删除了应用程序的所有 .m 文件。

现在 isKindOfClass 按预期工作。

感谢大家的支持。

【讨论】:

  • 我遇到了类似的问题。它不是应用程序的源文件,而是来自另一个项目的静态库,由应用程序目标和测试目标导入。
  • 遇到同样的问题,但在我的构建日志中没有得到“在两者中都实现”警告。
  • 我遇到了类似的问题,发现从模拟器调用重置内容和设置解决了问题
【解决方案2】:

您不应直接将 BOOL 值与 YES 进行比较。这可能会导致您的断言出现问题。这是有关该问题的背景参考:http://mobiledevelopertips.com/objective-c/of-bool-and-yes.html

【讨论】:

  • 我完全同意这一点 - 最好只测试结果,'if(foo)'。您使用 YES 返回一个 BOOL 值。
  • 第一个实现是在主帖中的更新 1。感谢您的支持
  • @LucaBartoletti 没问题,抱歉,这不是问题所在。关于这里有什么问题的任何更新?
  • @CarlVeazey 我发布了解决方案。
【解决方案3】:

使用 NSStringFromClass 将类名转换为字符串将避免 isKindOfClass 出现问题...示例:

if ([NSStringFromClass([AViewController class]) isEqualToString:NSStringFromClass([BViewController class])])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-19
    • 2020-03-18
    • 2012-06-14
    • 2014-11-15
    • 1970-01-01
    • 2012-07-02
    • 2011-09-07
    • 2013-03-03
    相关资源
    最近更新 更多