我觉得作为一名程序员,不断去深入挖掘代码的底层实现过程,这是一件非常有意思的事情,就像福尔摩斯探案一样,层层解析,得以真相。
首先,看如下代码段:
#import
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"Hello, World!");
Person *son = [[Person alloc]init];
}
return 0;
}
在mian函数中,我们创建了一个Person的类,那么在执行[[Person alloc]init]这段代码时做了什么,下面一步步去看
1、使用clang进行编译,执行以下命令:
clang -rewrite-objc main.m
2、执行上面代码后,会在目录文件下生成一个main.cpp文件
3、使用 open main.cpp命令打开文件,直接拉到文件底部,查看编译后的代码内容
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
NSLog((NSString *)&__NSConstantStringImpl__var_folders_cl_snxcxfl91ss0gvkz5wvcksjc0000gn_T_main_895957_mi_0);
Poson *son = ((Poson *(*)(id, SEL))(void *)objc_msgSend)((id)((Poson *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Poson"), sel_registerName("alloc")), sel_registerName("init"));
}
return 0;
}
开始源码查看
可以看到代码已经被转换,而之前
[[Person alloc]init]
已经变成
((Poson *(*)(id, SEL))(void *)objc_msgSend)((id)((Poson *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Poson"), sel_registerName("alloc")), sel_registerName("init"));
1、调用objc_msgSend发送消息
((Poson *(*)(id, SEL))(void *)objc_msgSend)
2、分别调用objc_getClass和sel_registerName两个方法
((id)objc_getClass("Poson"), sel_registerName("alloc")), sel_registerName("init"))
可以看到,调用了两个runtime方法,分别是:objc_getClass("Poson")和sel_registerName("alloc")
关系如下:
方法注册了两次,是因为alloc与init两个方法的调用。
3、查看objc_getClass方法的实现,从[[ https://opensource.apple.com/tarballs/objc4/]下载源码,进入到 objc-runtime.mm文件,搜索objc_getClass跳转到代码块,看到如下代码
Class objc_getClass(const char *aClassName)
{
if (!aClassName) return Nil;
// NO unconnected, YES class handler
return look_up_class(aClassName, NO, YES);
}
4、关键是看look_up_class这个方法,这个方法的实现如下:
Class
look_up_class(const char *name,
bool includeUnconnected __attribute__((unused)),
bool includeClassHandler __attribute__((unused)))
{
if (!name) return nil;
Class result;
bool unrealized;
{
mutex_locker_t lock(runtimeLock);
result = getClass(name);
unrealized = result && !result->isRealized();
}
if (unrealized) {
mutex_locker_t lock(runtimeLock);
realizeClass(result);
}
return result;
}
5、进入到realizeClass(result);方法,看它做了什么,这才是正菜
static Class realizeClass(Class cls)
{
runtimeLock.assertLocked();
const class_ro_t *ro;
class_rw_t *rw;
Class supercls;
Class metacls;
bool isMeta;
if (!cls) return nil;//如果参数为空,返回空
if (cls->isRealized()) return cls;//如果类已实现,返回类
assert(cls == remapClass(cls));
// fixme verify class is not in an un-dlopened part of the shared cache?
ro = (const class_ro_t *)cls->data();
if (ro->flags & RO_FUTURE) {
// This was a future class. rw data is already allocated.表示rw已经分配
rw = cls->data();
ro = cls->data()->ro;
cls->changeInfo(RW_REALIZED|RW_REALIZING, RW_FUTURE);
} else {
// Normal class. Allocate writeable class data.
rw = (class_rw_t *)calloc(sizeof(class_rw_t), 1);
rw->ro = ro;
rw->flags = RW_REALIZED|RW_REALIZING;
cls->setData(rw);
}
isMeta = ro->flags & RO_META;
rw->version = isMeta ? 7 : 0; // old runtime went up to 6
// Choose an index for this class.
// Sets cls->instancesRequireRawIsa if indexes no more indexes are available
cls->chooseClassArrayIndex();
if (PrintConnecting) {
_objc_inform("CLASS: realizing class '%s'%s %p %p #%u",
cls->nameForLogging(), isMeta ? " (meta)" : "",
(void*)cls, ro, cls->classArrayIndex());
}
// Realize superclass and metaclass, if they aren't already.
// This needs to be done after RW_REALIZED is set above, for root classes.
// This needs to be done after class index is chosen, for root metaclasses.
supercls = realizeClass(remapClass(cls->superclass));
metacls = realizeClass(remapClass(cls->ISA()));
#if SUPPORT_NONPOINTER_ISA
// Disable non-pointer isa for some classes and/or platforms.
// Set instancesRequireRawIsa.
bool instancesRequireRawIsa = cls->instancesRequireRawIsa();
bool rawIsaIsInherited = false;
static bool hackedDispatch = false;
if (DisableNonpointerIsa) {
// Non-pointer isa disabled by environment or app SDK version
instancesRequireRawIsa = true;
}
else if (!hackedDispatch && !(ro->flags & RO_META) &&
0 == strcmp(ro->name, "OS_object"))
{
// hack for libdispatch et al - isa also acts as vtable pointer
hackedDispatch = true;
instancesRequireRawIsa = true;
}
else if (supercls && supercls->superclass &&
supercls->instancesRequireRawIsa())
{
// This is also propagated by addSubclass()
// but nonpointer isa setup needs it earlier.
// Special case: instancesRequireRawIsa does not propagate
// from root class to root metaclass
instancesRequireRawIsa = true;
rawIsaIsInherited = true;
}
if (instancesRequireRawIsa) {
cls->setInstancesRequireRawIsa(rawIsaIsInherited);
}
// SUPPORT_NONPOINTER_ISA
#endif
// Update superclass and metaclass in case of remapping
cls->superclass = supercls;
cls->initClassIsa(metacls);
// Reconcile instance variable offsets / layout.
// This may reallocate class_ro_t, updating our ro variable.
if (supercls && !isMeta) reconcileInstanceVariables(cls, supercls, ro);
// Set fastInstanceSize if it wasn't set already.
cls->setInstanceSize(ro->instanceSize);
// Copy some flags from ro to rw
if (ro->flags & RO_HAS_CXX_STRUCTORS) {
cls->setHasCxxDtor();
if (! (ro->flags & RO_HAS_CXX_DTOR_ONLY)) {
cls->setHasCxxCtor();
}
}
// Connect this class to its superclass's subclass lists
if (supercls) {
addSubclass(supercls, cls);
} else {
addRootClass(cls);
}
// Attach categories
methodizeClass(cls);//分类设置
return cls;
}
realizeClass方法实现
1、创建了五个变量
const class_ro_t *ro; //保存着类的基本属性
class_rw_t *rw; // 里面有个 class_ro_t对象,
Class supercls;
Class metacls;
bool isMeta;
先简单了解一下Class对象的结构,每个objc_class都包含有class_data_bits_t数据位,其中储存了class_rw_t的指针地址和一些其他标记。class_rw_t中包含有属性方法协议列表,以及class_ro_t指针地址。而在class_ro_t结构中,储存的是编译器决定的属性方法协议
2、两个逻辑判断
if (!cls) return nil;//如果参数为空,返回空
if (cls->isRealized()) return cls;//如果类已实现,返回类
3、一个断言,主要依据是当前类等于remapClass(cls)就直接退出
4、通过(const class_ro_t *)cls->data()获取一个class_ro_t对象赋值给定义的ro;
ro = (const class_ro_t *)cls->data();//获取一个class的class_ro_t对象,用于判断
5、如果ro-flags已标记了,但是没有实现,则给rw和ro分别读取cls相应值
rw = cls->data();
ro = cls->data()->ro;
cls->changeInfo(RW_REALIZED|RW_REALIZING, RW_FUTURE);
如果没有被标记则:
rw = (class_rw_t *)calloc(sizeof(class_rw_t), 1);//创建一个class_rw_t对象
rw->ro = ro;//将ro赋值给rw.ro,ro = (const class_ro_t *)cls->data();
rw->flags = RW_REALIZED|RW_REALIZING;
cls->setData(rw);//设置累的data
6、接下来就是
// Update superclass and metaclass in case of remapping
cls->superclass = supercls;
cls->initClassIsa(metacls);//获取isa指针
// Reconcile instance variable offsets / layout.
// This may reallocate class_ro_t, updating our ro variable.
if (supercls && !isMeta) reconcileInstanceVariables(cls, supercls, ro);
// Set fastInstanceSize if it wasn't set already.
cls->setInstanceSize(ro->instanceSize);
// Copy some flags from ro to rw
if (ro->flags & RO_HAS_CXX_STRUCTORS) {
cls->setHasCxxDtor();
if (! (ro->flags & RO_HAS_CXX_DTOR_ONLY)) {
cls->setHasCxxCtor();
}
}
// Connect this class to its superclass's subclass lists
if (supercls) {
addSubclass(supercls, cls);
} else {
addRootClass(cls);
}
// Attach categories
methodizeClass(cls);//分类设置
最后调用的methodizeClass是使用分类时用的。
总结:
大体过了一遍创建流程,由于理解的还不是很深入,写的不是很透彻,再接再厉,加油!
参考资料:
https://www.cnblogs.com/vanch/p/9662424.html
https://segmentfault.com/a/1190000004992561
https://www.jianshu.com/p/3019605a4fc9