1. ARC帮我们做了什么?
使用LVVM + Runtime 结合帮我管理对象的生命周期
LVVM 帮我们在代码合适的地方添加release、retarn、autorelease等添加计数器或者减少计数器操作
Runtime 帮我们像__weak、copy等关键字的操作
2.initialize和load是如何调用的?它们会多次调用吗?
load方法说在应用加载的时候,Runtime直接拿到load的IMP直接去调用的,而不是像其他方式根据objc_msgSend(消息机制)来调用方法的
load_images(const char *path __unused, const struct mach_header *mh) {
// 准备class 和category
prepare_load_methods((const headerType *)mh);
// 调用load方法
call_load_methods();
}
void prepare_load_methods(const headerType *mhdr) {
classref_t *classlist =
_getObjc2NonlazyClassList(mhdr, &count);
for (i = 0; i < count; i++) {
schedule_class_load(remapClass(classlist[i]));
}
category_t **categorylist = _getObjc2NonlazyCategoryList(mhdr, &count);
for (i = 0; i < count; i++) {
category_t *cat = categorylist[i];
add_category_to_loadable_list(cat);
}
}
static void schedule_class_load(Class cls) {
// 开始递归,加载superclass
schedule_class_load(cls->superclass);
add_class_to_loadable_list(cls);
}
void call_load_methods(void) {
do {
while (loadable_classes_used > 0) {
call_class_loads();
}
more_categories = call_category_loads();
} while (loadable_classes_used > 0 || more_categories);
}
static void call_class_loads(void) {
// 在此add_class_to_loadable_list 里面准备了所有重写load的方法的类
struct loadable_class *classes = loadable_classes;
// Call all +loads for the detached list.
for ( int i = 0; i < used; i++) {
Class cls = classes[i].cls;
// 获取到load 方法的imp
load_method_t load_method = (load_method_t)classes[i].method;
// 调用laod 方法
(*load_method)(cls, SEL_load);
}
}
static bool call_category_loads(void) {
// 在prepare_load_methods 方法里面准备了所有重新load方法的category
struct loadable_category *cats = loadable_categories;
for (int i = 0; i < used; i++) {
// 获取到catgegory
Category cat = cats[i].cat;
// 获取category 的load 方法的IMP实现
load_method_t load_method = (load_method_t)cats[i].method;
cls = _category_getClass(cat);
if (cls && cls->isLoadable()) {
// 调用load方法
(*load_method)(cls, SEL_load);
}
}
}
void _class_initialize(Class cls) {
supercls = cls->superclass;
if (supercls && !supercls->isInitialized()) {
// 又是个递归
_class_initialize(supercls);
}
// 调用 initialize方法
callInitialize(cls);
}
// objc_msgSend 调用 initialize 方法
void callInitialize(Class cls) {
// **注意:因为使用了objc_msgSend,有可能调用class的 initialize **
objc_msgSend(cls, SEL_initialize);
}
总结:
load方法一个类只会调用一次(除去手动调用),而调用的数序是,从superclass -> class -> category,category里面的顺序是先编译,先调用
initialize方法,一个类可能会调用多次