load
是在 obj-c 运行时添加一个 class
时被调用的。
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/#//apple_ref/occ/clm/NSObject/load
假设在 obj-c 运行时中添加了一个 UIViewController,其中已包含 viewWillAppear: 方法,但您希望将其替换为另一种实现。因此,首先添加一个新方法 xxxWillAppear:。只有在 ViewController 类中添加了 xxxWillAppear: 方法之后,才能进行替换。
但作者也说:
例如,假设我们想要跟踪 iOS 应用程序中呈现给用户的每个视图控制器的次数,
因此,他试图演示一个应用程序可能有多个视图控制器的情况,但您不想为每个 ViewController 都保留 viewWillAppear: 实现。一旦 viewWillAppear: 的替换点被替换,那么只需要进行交换而不是添加即可。
也许 Objective C 运行时的源代码可以帮助:
static IMP
addMethod(Class cls, SEL name, IMP imp, const char *types, BOOL replace)
{
IMP result = nil;
rwlock_assert_writing(&runtimeLock);
assert(types);
assert(cls->isRealized());
method_t *m;
if ((m = getMethodNoSuper_nolock(cls, name))) {
if (!replace) {
result = _method_getImplementation(m);
} else {
result = _method_setImplementation(cls, m, imp);
}
} else {
method_list_t *newlist;
newlist = (method_list_t *)_calloc_internal(sizeof(*newlist), 1);
newlist->entsize_NEVER_USE = (uint32_t)sizeof(method_t) | fixed_up_method_list;
newlist->count = 1;
newlist->first.name = name;
newlist->first.types = strdup(types);
if (!ignoreSelector(name)) {
newlist->first.imp = imp;
} else {
newlist->first.imp = (IMP)&_objc_ignored_method;
}
attachMethodLists(cls, &newlist, 1, NO, NO, YES);
result = nil;
}
return result;
}
BOOL
class_addMethod(Class cls, SEL name, IMP imp, const char *types)
{
if (!cls) return NO;
rwlock_write(&runtimeLock);
IMP old = addMethod(cls, name, imp, types ?: "", NO);
rwlock_unlock_write(&runtimeLock);
return old ? NO : YES;
}
IMP
class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)
{
if (!cls) return nil;
rwlock_write(&runtimeLock);
IMP old = addMethod(cls, name, imp, types ?: "", YES);
rwlock_unlock_write(&runtimeLock);
return old;
}
如果你想深入了解,可以继续挖掘:
http://www.opensource.apple.com/source/objc4/objc4-437/