9

i'm working on a iOS5+ project (xcode 4.4.1 SDK 5.1)

i have this code inside a unit test:

[_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");

If i run the test, the test fail.

So i check with the debugger:

(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) 

In application:didFinishLaunchingWithOptions: i create a ScheduleViewController and i use it as rootController of the navigation controller. The debugger say it's correct. I don't understand what is wrong with the assert above.

Someone have idea about this?

Update

The first implementation of thE assert was:

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

The assert failed at the same way.

Update 2

As suggested in the comment i try to add this piece of code before the assert:

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

With the debugger i see:

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

Update 3

I added this line, as suggested in the comments, before the assert:

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

From the debug console:

vc_1=<ScheduleViewController: 0x993bdb0> class=ScheduleViewController
Luca Bartoletti
  • 2,435
  • 1
  • 24
  • 46
  • 5
    Did you try to remove the `==YES`? – dasdom Sep 12 '12 at 10:33
  • 1
    @dasdom `== YES` is unnecessary, but does it make a difference to the functionality? – trojanfoe Sep 12 '12 at 10:36
  • @trojanfoe It sure should not make any difference. – dasdom Sep 12 '12 at 10:37
  • Did you try to use the `nc_1.topViewController` in the `STAssertTrue()`? – dasdom Sep 12 '12 at 10:40
  • 1
    Are you sure it's failing at that `STAssertTrue()` statement and not elsewhere? – trojanfoe Sep 12 '12 at 10:42
  • Those answers really gave me a help with isKindOfClass : http://stackoverflow.com/questions/12173711/objective-c-understanding-iskindofclass – Andy M Sep 12 '12 at 10:52
  • 1
    If you add this line above the failing test, I'll bet it fails too. There is most likely some initialization step for OCUnit that your code missed: 'STAssertTrue(YES, @"Even YES fails");' If by some miracle that works, then extract your statement out of the STAssert and assign the value to a bool, log it, then STAssert on the BOOL. – David H Sep 12 '12 at 11:53
  • @DavidH STAssertTrue(YES,@""); doesn't fail. I try to add a BOOL variable as Update 2 in the post – Luca Bartoletti Sep 12 '12 at 11:59
  • 1
    So do more logging before 'BOOL vcBool': NSLog(@"vc_1=%@ class=%@", vc_1, NSStringFromClass([vc_1 class]));' I'm guessing vc_1 is nil, but by the time you get to the debugger its gotten set. – David H Sep 12 '12 at 12:47
  • 1
    Is ScheduleViewController in the Target of your unit test? This seems to be the same problem as: http://stackoverflow.com/questions/12159961/iskindofclass-returning-no-unexpectedly – vacawama Sep 12 '12 at 13:39
  • @vacawama Yes, it is in the target – Luca Bartoletti Sep 12 '12 at 13:50
  • @DavidH Ok, you find the result in Update 3. (Tnx for the support) – Luca Bartoletti Sep 12 '12 at 13:51
  • 1
    My concern is that somehow the values are changing between the time the log messages are printed and when you get into the debugger. Please AFTER the Update3 log message add your assignment to vcBool, then 'NSLog(@"vcBool=%d result=%d", vcBool, [vc_1 isKindOfClass:(Class)[ScheduleViewController class]]);'. That said this is truely bizarre. – David H Sep 12 '12 at 15:02
  • Are you running this on the device or the simulator? Is there any difference in behavior between the two? – Carl Veazey Sep 12 '12 at 16:49
  • No difference between simulator and device – Luca Bartoletti Sep 13 '12 at 19:29
  • possible duplicate of [isMemberOfClass returns no when ViewController is instantiated from UIStoryboard](http://stackoverflow.com/questions/11675256/ismemberofclass-returns-no-when-viewcontroller-is-instantiated-from-uistoryboard) – jscs Sep 13 '12 at 19:36

3 Answers3

22

I found the solution.

It's the inverse of the solution presented in the post linked by @vacawama in the comments. I had all *.m source of the app target in the test target too. While i was searching for a solution to the isKindOfClass problem i noticed a lot of warning on the console at the begin of the test session. The warnings was like this:

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.

I removed all .m files of the application from test target.

Now isKindOfClass works as expected.

Thank to all for the support.

Luca Bartoletti
  • 2,435
  • 1
  • 24
  • 46
  • 2
    I had a similar problem. Instead of the application's source files, it was a static library from another project that was imported by both the application target and test target. – jamesmoschou Jan 22 '13 at 09:06
  • 1
    Bit by this same problem but did not get the "is implemented in both" warning in my build logs. – owenfi Aug 19 '13 at 05:03
  • I had a similar problem and found calling reset content and settings from the simulator fixed the problem – Robert Wagstaff Nov 09 '15 at 01:29
3

You shouldn't directly compare BOOL values to YES. It's possible this is causing the issue with your assert. Here's a reference with background on the issue: http://mobiledevelopertips.com/objective-c/of-bool-and-yes.html

Carl Veazey
  • 18,392
  • 8
  • 66
  • 81
2

Converting a class name to string with NSStringFromClass will avoid problems with isKindOfClass... example:

if ([NSStringFromClass([AViewController class]) isEqualToString:NSStringFromClass([BViewController class])])
omanosoft
  • 4,239
  • 1
  • 9
  • 16