Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inspecting nil value returned by NSClassFromString

We can create a class by using NSClassFromString:

Class class = NSClassFromString(@"someClass");
id object = [[class alloc] init];
[object test];

It's no problem here.

NSClassFromString would return nil if a class given by the string does not exist.

Fair enough and calling [object test];, when object is nil (because class is nil) would not cause any problem.

As an experiment, I changed @"someClass" to something else that does not exist. By logging the value of class (when NSClassFromString returns nil) it shows 0x0. And subsequently I tried to replace as a test:

id object = [[class alloc] init];

with the following one by one:

id object = [[Nil alloc] init];

id object = [[nil alloc] init];

id object = [[NSNull alloc] init];

Only id object = [[NSNull alloc] init]; does not cause any compile error but will cause a crash when it reaches to this line:

[object test];

So my question is, why can't I replace class with either nil or Nil, but when NSClassFromString returns nil and assign it to Class class and calling this [[class alloc] init]; would work? class is also nil here.

Adding error message for cases when id object = [[Nil alloc] init]; or id object = [[nil alloc] init]; is applied.

Bad receiver type of 'void *'.

like image 438
Unheilig Avatar asked Feb 14 '23 09:02

Unheilig


2 Answers

nil is of type void*, not id. You cannot send messages to a void*.

NULL, Nil, and nil are type void* so that may be assigned to anything. If nil was type id then you couldn't do this:

char* foo = nil;

which is not a useful limitation.

If you really want to send a message to nil you need to cast it to the correct type:

[(id)nil description];
like image 150
Darren Avatar answered Feb 16 '23 04:02

Darren


The Objective C runtime can handle the runtime situation of sending a message to nil, but if you already know at compile time that the target is nil, nothing good can possibly come out of it, so the compiler is doing you a favor by flagging a construct that is known not to accomplish anything.

Edit: @Darren is right, nil is a void *, not an id, so this fails for type checking reasons. Something like [[(id)nil alloc] init] does in fact compile. I still think a compiler should flag sending messages to known nils, but as a matter of fact, it doesn't.

like image 25
microtherion Avatar answered Feb 16 '23 03:02

microtherion