Objetive-C +load方法研究

  • load方法的执行时机
          Objetive-C 的runtime会在一个类的所有方法加载到内存中时调用这个类的+load() 方法,因为每个类的方法只是加载一次,所以每个+load()方法只调用一次。
          加载一个类的方法会在一个进程启动开始的时候,这个时候进程的业务代码没有还没有开始执行。
          对于动态库中的类,类的+load方法会在动态库加载进进程的内存空间时的时候执行
 
  • load的执行次序
          +load的方法会从父类到子类的顺序执行,对于一个类的扩展中的Load方法,执行顺序是不确定的。
          +load的方法不遵从其它继承方法执行的规律,只有一个类或者扩展存在load方法的时候才会执行。原因是load的方法的imp查找是直接通过特殊的方法查找的,见
          
/***********************************************************************
* _class_getLoadMethod
* fixme
* Called only from add_class_to_loadable_list.
* Locking: runtimeLock must be read- or write-locked by the caller.
**********************************************************************/
IMP 
_class_getLoadMethod(Class cls_gen)
{
    rwlock_assert_locked(&runtimeLock);

    class_t *cls = newcls(cls_gen);
    const method_list_t *mlist;
    uint32_t i;

    assert(isRealized(cls));
    assert(isRealized(cls->isa));
    assert(!isMetaClass(cls));
    assert(isMetaClass(cls->isa));

    mlist = cls->isa->data()->ro->baseMethods;
    if (mlist) for (i = 0; i < mlist->count; i++) {
        method_t *m = method_list_nth(mlist, i);
        if (0 == strcmp((const char *)m->name, "load")) {
            return m->imp;
        }
    }

    return NULL;
}

 
 
     下面是一个Demo
 
 
 
@interface initTest : NSObject
@end
 
@interface sub1 : initTest
@end
 
@interface sub2 : sub1
@end
 
@interface sub2 (category1)
@end
@interface sub2 (category2)
@end
 
 
//实现
 
@implementation initTest

//+(void)initialize
//{
//    NSLog(@"%s|%@  ",__func__ ,[self class]);
//}

+(void)load
{
    NSLog(@"%s  ",__func__ );
}

@end


@implementation sub1

//+(void)initialize
//{
//    NSLog(@"%s|%@  ",__func__ ,[self class]);
//}

//+(void)load
//{
//    NSLog(@"%s  ",__func__ );
//}
@end


@implementation sub2

//+(void)initialize
//{
//    NSLog(@"%s|%@  ",__func__ ,[self class]);
//}

+(void)load
{
    NSLog(@"%s  ",__func__ );
}

@end


@implementation sub2 (category1)

+(void)load
{
    NSLog(@"%s  ",__func__ );
}

@end

@implementation sub2 (category2)

+(void)load
{
    NSLog(@"%s  ",__func__ );
}
@end
 
执行结果如下:
 
2015-05-26 13:09:37.955 OCinitTest[79585:72506319] +[initTest load] 
2015-05-26 13:09:37.956 OCinitTest[79585:72506319] +[sub2 load] 
2015-05-26 13:09:37.956 OCinitTest[79585:72506319] +[sub2(category1) load] 
2015-05-26 13:09:37.956 OCinitTest[79585:72506319] +[sub2(category2) load]  
 
  • load方法可以用来做什么
          对于一个方法的Swizzle,因为这个时候改变runtime中得方法比执行中改变更安全

你可能感兴趣的:(load)