我们可以使用NSClassFromString
创建一个类:
Class class = NSClassFromString(@"someClass");
id object = [[class alloc] init];
[object test];
这里没问题。
如果字符串给出的类不存在, NSClassFromString
将返回nil
。
当对象为零(因为类为[object test];
时),并且调用nil
时不会引起任何问题。
作为实验 ,我将@"someClass"
更改为其他不存在的内容。
通过记录class
的值(当NSClassFromString
返回nil
时),它会显示0x0
。
随后我尝试将其替换为测试:
id object = [[class alloc] init];
以下逐一:
id object = [[Nil alloc] init];
id object = [[nil alloc] init];
id object = [[NSNull alloc] init];
只有id object = [[NSNull alloc] init];
不会导致任何编译错误,但会在到达此行时导致崩溃:
[object test];
所以我的问题是 ,为什么我不能用class
或nil
替换Nil
,但是当NSClassFromString
返回nil
并将其分配给Class class
时,调用此[[class alloc] init];
会有效吗?此处class
也是nil
。
在应用id object = [[Nil alloc] init];
或id object = [[nil alloc] init];
的情况下添加错误消息。
错误的接收器类型' void *'。
答案 0 :(得分:5)
nil
的类型为void*
,而不是id
。您无法向void*
发送消息。
NULL,Nil和nil是类型void*
,因此可以分配给任何东西。如果nil是id
类型,则您无法执行此操作:
char* foo = nil;
这不是一个有用的限制。
如果您确实要向nil
发送消息,则需要将其转换为正确的类型:
[(id)nil description];
答案 1 :(得分:3)
Objective C运行时可以处理向nil
发送消息的运行时情况,但如果您在编译时已经知道目标是nil
,则可能没有任何好处,所以编译器通过标记一个已知不会完成任何事情的构造来帮助你。
修改: @Darren是对的,nil
是void *
,而不是id
,因此出于类型检查原因失败。像[[(id)nil alloc] init]
之类的东西确实可以编译。我仍然认为编译器应该标记向已知的nil
发送消息,但事实上,它并不。