【问题标题】:isKindOfClass and NSStringFromClass disagree about UIApplicationDelegateisKindOfClass 和 NSStringFromClass 不同意 UIApplicationDelegate
【发布时间】:2011-07-18 20:33:05
【问题描述】:

我正在对 iPhone 应用程序进行简单的 OCUnit 测试,只是想断言应用程序委托是我期望的类的一个实例。我没想到这个测试会很有用,但结果却揭示了我对 Objective C 的误解。

我首先得到对委托的引用。然后我记录返回的类名。就我而言,输出正确显示“应用程序委托的类名是 CalculatorAppDelegate”。

但是,下一行的断言失败了,我不明白为什么。

- (void)testAppDelegate 
{
    id appDelegate = [[UIApplication sharedApplication] delegate];
    NSLog(@"app delegate's class name is %@", NSStringFromClass([appDelegate class]));
    NSLog(@"is it kind? %i", [appDelegate isKindOfClass:[CalculatorAppDelegate class]]);
    NSLog(@"is it member? %i", [appDelegate isMemberOfClass:[CalculatorAppDelegate class]]);
    NSLog(@"class == class %i", [appDelegate class] == [CalculatorAppDelegate class]);
    STAssertTrue([appDelegate isKindOfClass:[CalculatorAppDelegate class]], @"wtf");
}

什么情况会导致 NSStringFromClass() 返回正确的类名,而 isKindOfClass 返回 false?

2011-03-19 15:51:13.864 Calculator[40092:207] app delegate's class name is CalculatorAppDelegate
2011-03-19 15:51:13.864 Calculator[40092:207] is it kind? 0
2011-03-19 15:51:13.865 Calculator[40092:207] is it member? 0
2011-03-19 15:51:13.865 Calculator[40092:207] class == class 0
/Users/pohl/Developer/FoundationCalculator/CalculatorTests/CalculatorBrainTests.m:37: error: -[CalculatorBrainTests testAppDelegate] : "[appDelegate isKindOfClass:[CalculatorAppDelegate class]]" should be true. wtf
Test Case '-[CalculatorBrainTests testAppDelegate]' failed (0.002 seconds).

【问题讨论】:

    标签: iphone objective-c uiapplicationdelegate ocunit cs193p


    【解决方案1】:

    尝试注销操作的返回值是什么

    NSLog(@"is it kind? %i", [appDelegate isKindOfClass:[CalculatorAppDelegate class]]);
    

    你甚至可以测试它是否是成员:

    NSLog(@"is it member? %i", [appDelegate isMemberOfClass:[CalculatorAppDelegate class]]);
    

    不确定它是否会有所帮助,但它是一个起点

    【讨论】:

    • 善良吗? 0 是会员吗? 0
    • 请尝试[appDelegate class] == [CalculatorAppDelegate class]
    • 好主意。 NSLog(@"%i", [appDelegate class] == [CalculatorAppDelegate class]); 的输出为 0
    • 好的最后一个方法[NSStringFromClass([appDelegate class]) isEqualToString:NSStringFromClass([CalculatorAppDelegate class])]
    • 好的,它的输出是 1。所以这意味着我们有两个不同的类对象,它们拥有相同的名称。会不会是 OCUnit 在这里做了一些奇特的事情?
    【解决方案2】:

    您没有正确配置测试目标。如果您关注this guide for unit testing applications,您应该有 3 个目标:CalculatorCalculatorTestsCalculatorTesting。 检查 CalculatorTests 中的“构建阶段”部分。在“编译源”中,只有 SenTestCase 源文件应在此处列出。我猜你在那里添加了 CalculatorAppDelegate.m 和其他文件 - 这会导致相同源文件的重复程序集,然后在你构建 CalculatorTesting时链接到同一个应用程序> 目标。这就解释了为什么你的断言失败了。

    编辑:刚刚意识到您不需要 Xcode 4 中的 CalculatorTesting 目标。只需转到 Project > Edit Schemes... 并确保单元测试bundle 列在 Test 部分。然后你可以使用 Cmd-U 运行单元测试。

    【讨论】:

    • 我在 XCode4 中新建了这个项目,它自动为我设置了单元测试目标。我有很多测试,其中许多断言都运行良好。只有这一个断言失败了。我的目标设置不正确是否仍然存在?看起来没有 CalculatorTesting 目标,所以也许上面的断言就是他们所说的需要在设备中运行的应用程序测试?在相关说明中,我认为您链接到的页面上的说明与 XCode 4 设置目标的方式不对应。关于如何在 4 中制作目标的任何提示?
    • 我很确定您没有正确设置目标。我也在使用 Xcode 4 并测试了你的问题。在 Xcode 4 中,您必须在项目概览中选择您的正常应用程序目标并复制它(Cmd-D)。将其命名为 CalculatorTesting 并将 OCUnit 测试目标添加为依赖项。将活动方案设置为新目标并编辑此方案。选择左侧的测试并在那里添加您的测试包。现在您可以使用 Cmd-U 运行您的应用程序测试。
    • 我在 xcode 4 中创建了一个演示项目来证明我的观点 (db.tt/sQLXo9P)。有2个方案:第一个执行目标MyTestTests1并成功。第二个执行目标 MyTestTests2 并失败。这些目标之间的区别在于“编译源”构建阶段。
    • 感谢您一直以来的关注。我已经下载了你的测试项目,我可以在 MyTestTests1 和 MyTestTests2 之间来回切换,我同意你已经重现了我的问题。我也同意 1 和 2 之间唯一明显的区别是 MyTestAppDelegate.m 在两个包中每个包的“构建阶段”选项卡下的“编译源”中是否存在。这既令人振奋又令人沮丧,因为我的 CalculatorAppDelegate.m 源文件已经出现在我的 CalculatorTests 包的“编译源”中。我会继续思考这个问题。
    • 最终,我求助于创建一个新项目。我立即将此断言添加到新项目中,并且它成功了。然后,我将旧项目中的代码和资源复制到新项目中,边走边重复运行单元测试,直到新项目像旧项目一样运行。这个问题从未出现在新项目中。然后我试图仔细检查这两个项目之间的差异,看看是什么导致了这种差异,但没有运气。我认为 project.pbxproj 文件中可能存在一些差异,但很难区分。再次感谢您。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多