IsKindOfClass Behavior

Can someone explain why isKindOfClass returns different results depending on how the instance was created?

@interface BaseClass ... @interface DerivedClassA : BaseClass ... DerivedClassA *instance = [[DerivedClassA alloc] init]; [instance isKindOfClass:[BaseClass class]]; // yields YES Class c = NSClassFromString(@"DerivedClassA"); id instance = [[c alloc] init]; [instance isKindOfClass:[BaseClass class]]; // yields NO 

Everything that I can extract from the two types in the debugger is identical. I can even compare both results of NSStringFromClass ([class superclass]) and they are equal.

I need to miss something simple.

Updated Code

This is the unit test code.

 LightingUnit *u1 = [[LightingUnit alloc] init]; STAssertTrue([u1 isKindOfClass:[ModelBase class]], @"should be derived from base"); Class uc = NSClassFromString(@"LightingUnit"); id u2 = [[uc alloc] init]; STAssertTrue([u2 isKindOfClass:[ModelBase class]], @"should be derived from base"); 

Here are the class definitions.

 @interface ModelBase : NSObject @property (readonly) NSString *__type; - (id)initWithDictionary:(NSDictionary *)dictionary; - (NSMutableDictionary *)dictionary; @end @interface LightingUnit : ModelBase @property (strong, nonatomic) NSString *name; @property NSInteger unitId; @end 

Possible answer

When I run this logic outside the test environment, it works without problems. Obviously, the only difference is removing the STAssertTrue statements and replacing them with my conditions. In this case, they both return YES. I even tried to create a simplified example (no ivars in the database or derivative), and it fails in testing, but it works in the standard runtime.

Any ideas why this might be a problem while testing? Is my test target missing?

solvable

I have included .m files in compilation targets for testing purposes. After removal, it began to behave as expected. Thanks to this post for helping me resolve this issue.

+7
source share
2 answers

I added my code to the test application. I had to change the name of the two instance variables, after which the compiler gave me a warning ("Class method" + "not found"), and the program crashed on startup.

Then I changed this line:

 @interface BaseClass : NSObject 

i.e. I got BaseClass from NSObject . There are no more compiler warnings, and the code works as expected, i.e. The second isKindOfClass returns YES.

I do not know if the missing NSObject cause of your problem. If this is not so, then someone else should intervene. If so, I wonder how you could even run your code.

+2
source

Whether BaseClass from NSObject result of this code. Here are two possibilities:


 @interface BaseClass 

If you defined BaseClass without inheriting from NSObject , then, frankly, I am surprised that the compiler allows you to get away with setting up your instance variable. If you have not defined your +alloc and -init on BaseClass (which is possible), then the first line of your test will not work at all. If you have identified the appropriate method +alloc and -init , you will still encounter problems with -isKindOfClass: since you will also need to determine this yourself. So basically it wonโ€™t work, let's look at the next option ...


 @interface BaseClass : NSObject 

The first line of your test (creating instance ) should work fine.

[instance isKindOfClass:[BaseClass class]] returns the corresponding YES value.

class c initialization should work correctly.

I suspect something is missing here because the last line should return YES with the code you sent (assuming BaseClass inheriting from NSObject ) ... The last line should return YES . I suspect that it is possible that instance somehow ended up holding nil through the incorrect initialization of / typo / etc. In this case, sending the message, it will simply return nil , and thus sending -isKindOfClass will result in NO .

+2
source

All Articles