当从 UIStoryboard 实例化 ViewController 时,isMemberOfClass 返回 no
Posted
技术标签:
【中文标题】当从 UIStoryboard 实例化 ViewController 时,isMemberOfClass 返回 no【英文标题】:isMemberOfClass returns no when ViewController is instantiated from UIStoryboard 【发布时间】:2012-07-26 17:59:54 【问题描述】:我有一个 OCUnit 测试类:PatientTestViewControllerTests。下面是界面:
@interface PatientTestViewControllerTests : SenTestCase
@property (nonatomic, strong) PatientTestViewController *testController;
@end
和设置:
- (void) setUp
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Testing" bundle:nil];
self.testController = [storyboard instantiateInitialViewController];
“测试”故事板是我的应用程序中唯一的故事板,并被设置为应用程序的主故事板。 PatientTestViewController 被设置为情节提要的唯一视图控制器。
我的测试班有一个测试:
- (void) testInitialTestingStoryboardViewIsPatientTest
STAssertTrue([self.testController isMemberOfClass:[PatientTestViewController class]], @"Instead of the %@, we have %@",[PatientTestViewController class], [self.testController class]);
此测试失败并显示以下日志消息:
错误:-[PatientTestViewControllerTests testInitialTestingStoryboardViewIsPatientTest]:“[self.testController isMemberOfClass:[PatientTestViewController class]]”应该为真。我们使用 PatientTestViewController
代替 PatientTestViewController这怎么可能?自从
[self.testController isMemberOfClass:[PatientTestViewController class]]
显然是假的,测试日志怎么能说两者都是
[self.testController class]
和 [PatientTestViewController class]
看起来一样吗?
附加信息:
在测试中使用[self.testController isKindOfClass:[PatientTestViewController class]]
也会失败
使用[self.testController class] == [PatientTestViewController class]
也会失败。
使用[self.testController isKindOfClass:[UIViewController class]]
PASSES。
[self.testController isMemberOfClass:[UIViewController
class]]
失败。
【问题讨论】:
出于好奇,NSLog(@"Expected address: %p, actual: %p",[PatientTestViewController class], [self.testController class]);
长什么样子?
@JoshCaswell 啊哈。有趣的问题!和一个有趣的答案。 “预期地址:0x679fa48,实际:0x59bc” 那么……这是什么意思?显然它们是不同的内存地址......但是 isMemberOfClass 测试的对象是什么?是严格的对象相等吗,比如'=='?
@JoshCaswell 有趣的是,如果我使用标准的 alloc/init 在 setUp 中实例化 testController 对象,则测试通过没有问题,并且两个地址相同。那么为什么[UIStoryboard instantiateInitialViewController]
会返回不同的东西......它有什么不同呢?
我不确定isMemberOfClass:
如何在内部检查相等性。我有点怀疑 UIStoryboard 出于某种原因创建了一个虚拟替代类。可能是某种懒惰。怎么样:如果你给testController
发消息,然后做isMemberOfClass:
,isKindOfClass:
,然后打印地址会怎样?
我想你可能会在这里做点什么。向testController
发送消息并没有改变任何东西(地址仍然存在相同的差异)。但是,我创建了一个新项目来复制问题,但我无法复制它。这两个项目之间唯一真正的区别是我在摆弄我原来的故事板。我一定做了……什么。
【参考方案1】:
问题可能是您的视图控制器的 .m 文件包含在两个目标中,即应用程序和测试包中。 ocunit(以及 Kiwi 等衍生产品)使用测试工具,使应用程序中包含的类可用于测试,而无需显式包含它们的实现。
同时包含这两个副本为您提供了同一类的两个副本,这就是为什么它们具有相同的描述但内存地址不同的原因。
【讨论】:
目瞪口呆。就是这样。从测试目标和 blammo 中删除了 .m 文件。一切都会过去。我习惯了 GHUnit,你必须在两个目标中都包含 .m 文件。 谢谢 - 你刚刚解决了 HOURS 令人头疼和讨厌的创建 NSStrings-from-class-names 变通办法! 拯救我的一天!!!谢谢你指出这一点。我在我的测试项目中添加了我的模型文件,但不需要它。 要回答这个问题,从测试目标中删除源文件后,您可能需要set up the symbols to unhide themselves。【参考方案2】:您通常需要isKindOfClass:
而不是isMemberOfClass:
。不同之处在于,如果接收者是相关类的子类的成员,isKindOfClass:
将返回 YES
,而 isMemberOfClass:
在相同情况下将返回 NO
。
您也可以使用[self.testController class] == [PatientTestViewController class]
直接比较类。
【讨论】:
感谢您的回复。我希望测试是具体的,这就是我使用 isMemberOfClass 的原因。故事板的初始视图应该完全是 PatientTestViewController,而不是子类。但是,我确实也尝试过 isKindOfClass,只是为了确定。没有骰子。我喜欢 '==' 测试的想法,但它也不起作用。 :( 我将在问题中添加一些其他信息以及我尝试过的其他信息。以上是关于当从 UIStoryboard 实例化 ViewController 时,isMemberOfClass 返回 no的主要内容,如果未能解决你的问题,请参考以下文章
如何实例化第二个 ViewController 并停止第一个 ViewController 的方法
如何删除最后一个实例化的ViewController,最后一个TableViewController变为活动状态