load_images的作用?
在objc
的开源代码中注释是这么写的。
Process +load in the given images which are being mapped in by dyld。
意思就是处理由dyld
映射的image中的+load
方法。
源码探究
接下来我们来看看load_images
的源码。
void
load_images(const char *path __unused, const struct mach_header *mh)
{
// Return without taking locks if there are no +load methods here.
if (!hasLoadMethods((const headerType *)mh)) return;
recursive_mutex_locker_t lock(loadMethodLock);
// Discover load methods
{
mutex_locker_t lock2(runtimeLock);
prepare_load_methods((const headerType *)mh);
}
// Call +load methods (without runtimeLock - re-entrant)
call_load_methods();
}
这段代码中主要包含两个部分,一个是prepare_load_methods
,一个是call_load_methods
。
prepare_load_methods
void prepare_load_methods(const headerType *mhdr)
{
size_t count, i;
runtimeLock.assertLocked();
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];
Class cls = remapClass(cat->cls);
if (!cls) continue; // category for ignored weak-linked class
if (cls->isSwiftStable()) {
_objc_fatal("Swift class extensions and categories on Swift "
"classes are not allowed to have +load methods");
}
realizeClassWithoutSwift(cls);
assert(cls->ISA()->isRealized());
add_category_to_loadable_list(cat);
}
}
在这个阶段主要做了以下几件事情。
- 获取所有的非懒加载类(也就是实现了
+(void)load
方法的类)。 - 通过
schedule_class_load
递归处理本类的所有父类,最终调用add_class_to_loadable_list
把Class
和+load
方法存进一个结构体数组中。 - 获取所有非懒加载的分类。
- 调用
realizeClassWithoutSwift
对主类进行处理。 - 将分类中的
Class
和+load
方法添加进另一个管理分类+load
方法的结构体数组中。
至此在调用之前的预处理工作就做完了。
call_load_methods
调用所有的+(void)load
方法。
void call_load_methods(void)
{
static bool loading = NO;
bool more_categories;
loadMethodLock.assertLocked();
// Re-entrant calls do nothing; the outermost call will finish the job.
if (loading) return;
loading = YES;
void *pool = objc_autoreleasePoolPush();
do {
// 1. Repeatedly call class +loads until there aren't any more
while (loadable_classes_used > 0) {
call_class_loads();
}
// 2. Call category +loads ONCE
more_categories = call_category_loads();
// 3. Run more +loads if there are classes OR more untried categories
} while (loadable_classes_used > 0 || more_categories);
objc_autoreleasePoolPop(pool);
loading = NO;
}
- 针对所有的类进行遍历调用。
-
call_category_loads
对当前类的所有分类进行遍历调用。 - 先本类后分类。
- 父类的方法优先于分类。
网友评论