When I try to compile the following code:
int main(int argc, const char * argv[])
{
@autoreleasepool {
[NSObject init];
}
return 0;
}
compiler let it build and then the app crashes in runtime with the following exception:
2017-08-14 14:56:07.937859-0700 NSObjectInit[30512:11241814] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSObject<0x7fff9fd83140> init]: cannot init a class object.'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff818e32cb __exceptionPreprocess + 171
1 libobjc.A.dylib 0x00007fff966f348d objc_exception_throw + 48
2 CoreFoundation 0x00007fff8196517f +[NSObject(NSObject) init] + 127
3 NSObjectInit 0x0000000100000f2d main + 61
4 libdyld.dylib 0x00007fff96fd9235 start + 1
5 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
As I understand, there is +init method in NSObject class, but I didn't find it in public headers and if it is private, complier should tell us that there is no such method. Any ideas why compiler let us build this code?
Classes are themselves objects. There is an implicit "meta-class" for each class and the class is the one and only instance of that meta-class. What we normally think of as a "class method on class Foo" is also an instance method on class meta-Foo.
In a further quirk, the meta-class of the root class of a class hierarchy is a subclass of the root class itself. That is meta-NSObject
inherits from NSObject
. The class NSObject
is an instance of itself!
So, any instance method of NSObject
is also a class method of NSObject
. That is, it can be invoked on the NSObject
class itself. That's why the compiler doesn't have a problem with [NSObject init]
.
http://sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html