本章内容描述
- 本章的源码依旧是在 objc 源码中。
- 类的实现 realizeClassWithoutSwift 重点方法
- 运行的主线为: Read_images -》realizeClassWithoutSwift -》 methodizeClass
- 懒加载与非懒加载
- 分类的创建
一、realizeClassWithoutSwift
- 下面源码只显示关键代码 ,一步一步探索类的实现
static Class realizeClassWithoutSwift(Class cls, Class previously)
{
runtimeLock.assertLocked();
class_rw_t *rw;
Class supercls;
Class metacls;
if (!cls) return nil;
if (cls->isRealized()) {
validateAlreadyRealizedClass(cls);
return cls;
}
ASSERT(cls == remapClass(cls));
auto ro = (const class_ro_t *)cls->data();
auto isMeta = ro->flags & RO_META;
if (ro->flags & RO_FUTURE) {
rw = cls->data();
ro = cls->data()->ro();
ASSERT(!isMeta);
cls->changeInfo(RW_REALIZED|RW_REALIZING, RW_FUTURE);
} else {
rw = objc::zalloc<class_rw_t>();
rw->set_ro(ro);
rw->flags = RW_REALIZED|RW_REALIZING|isMeta;
cls->setData(rw);
}
supercls = realizeClassWithoutSwift(remapClass(cls->getSuperclass()), nil);
metacls = realizeClassWithoutSwift(remapClass(cls->ISA()), nil);
cls->setSuperclass(supercls);
cls->initClassIsa(metacls);
if (supercls && !isMeta) reconcileInstanceVariables(cls, supercls, ro);
cls->setInstanceSize(ro->instanceSize);
if (ro->flags & RO_HAS_CXX_STRUCTORS) {
cls->setHasCxxDtor();
if (! (ro->flags & RO_HAS_CXX_DTOR_ONLY)) {
cls->setHasCxxCtor();
}
}
if ((ro->flags & RO_FORBIDS_ASSOCIATED_OBJECTS) ||
(supercls && supercls->forbidsAssociatedObjects()))
{
rw->flags |= RW_FORBIDS_ASSOCIATED_OBJECTS;
}
if (supercls) {
addSubclass(supercls, cls);
} else {
addRootClass(cls);
}
methodizeClass(cls, previously);
return cls;
}
二、methodizeClass
- 对象的方法列表进行处理的方法
static void methodizeClass(Class cls, Class previously)
{
runtimeLock.assertLocked();
bool isMeta = cls->isMetaClass();
auto rw = cls->data();
auto ro = rw->ro();
auto rwe = rw->ext();
method_list_t *list = ro->baseMethods();
if (list) {
prepareMethodLists(cls, &list, 1, YES, isBundleClass(cls), nullptr);
if (rwe) rwe->methods.attachLists(&list, 1);
}
property_list_t *proplist = ro->baseProperties;
if (rwe && proplist) {
rwe->properties.attachLists(&proplist, 1);
}
protocol_list_t *protolist = ro->baseProtocols;
if (rwe && protolist) {
rwe->protocols.attachLists(&protolist, 1);
}
if (previously) {
if (isMeta) {
objc::unattachedCategories.attachToClass(cls, previously,
ATTACH_METACLASS);
} else {
objc::unattachedCategories.attachToClass(cls, previously,
ATTACH_CLASS_AND_METACLASS);
}
}
objc::unattachedCategories.attachToClass(cls, cls,
#endif
}
1. 扩展 read_images
- 条件控制进行一次的加载
- 修复预编译阶段的 @selector 的混乱情况
- 错误混乱类的处理
- 修复重映射一些没有被镜像文件加载进来的的类
- 修复一些消息
- 类中有协议的时候, readProtocol
- 修复没有被加载的协议
- 分类处理
- 类的加载处理
- 没有被处理的类,优化被侵犯的类
三、懒加载与非懒加载类的区别
当前类是否实现了load方法,实现了load方法就是非懒加载,反之就是懒加载
1.懒加载执行顺序
数据加载推迟到第一次消息的时候
- lookUpImpOrForward
- realizeClassMayBeSwiftMaybeRelock
- realizeClassWithoutSwift
- methodizeClass
2. 非懒加载的的执行顺序
map_images的时候回加载所有类的数据
- readClass
- _getObjc2NonlazyClassList
- realizeClassWithoutSwift
- methodizeClass
四. category 分类的介绍
- 底层也是个结构体
struct _category_t {
const char *name;
struct _class_t *cls;
const struct _method_list_t *instance_methods;
const struct _method_list_t *class_methods;
const struct _protocol_list_t *protocols;
const struct _prop_list_t *properties;
}
- 分类没有元类
- 源码路径 : attachToClass -》 attachCategories
- rwe内存分配源码:
class_rw_ext_t *extAllocIfNeeded() {
auto v = get_ro_or_rwe();
if (fastpath(v.is<class_rw_ext_t *>())) {
return v.get<class_rw_ext_t *>(&ro_or_rw_ext);
} else {
return extAlloc(v.get<const class_ro_t *>(&ro_or_rw_ext));
}
}
- rwe被alloc的时机: 可以搜索整个OBJC 源码工程 ,关键字 extAlloc。 会发现在:动态添加属性, 动态添加方法,添加协议,添加分类的时候才会被创建。
总结
1. ro 、rw 、rwe的区别?
类包含了:元类,父类, flags, method cache ,还有类本身,同时还拥有指向一片干净内存的指针(clean memory), 这就是Ro,加载到内存后,就不能再修改。 相对的,就存在dirty meomory,这就是rw, rw在程序运行时发生更改的内存,但是在实际应用中,类的使用量不多,这样就造成了内存浪费, 所以苹果设计出了 rwe,这样就会把rw中的方法,属性, 协议, 分类等都放入了rwe。
|