load和initialize方法

2017-08-25  本文已影响14人  sun5kong

[图片上传中。。。(1)]###load

load方法在这个文件被程序装载时调用. 只要在compile source中出现的文件总是会被装载, 这与这个类是否被调用到无关, 因此load 方法总是在main函数之前被调用.

调用规则:

如果一个类实现了load方法, 在调用这个方法前会调用父类的load方法. 而且这个过程是自动完成的, 并不需要我们手动实现:

//In Parent.m
+ (void)load {
  NSLog(@"Load class Parent");
}
//In Child.m, 继承Parent
+ (void)load {
  NSLog(@"Load class Child");
}
// 运行结果:
/*
    2016-02-01 21:28:14.379 load[11789:1435378] Load Class Parent
    2016-02-01 21:28:14.380 load[11789:1435378] Load Class Child
    2016-02-01 22:28:14.381 load[11789:1435378] Load Class Child+load
*/

如果一个类没有实现load方法, 那么久不会调用它父类的load方法, 这一点与正常的类继承和方法调用都不一样, 需要额外注意.

执行顺序

load方法调用时,系统处于脆弱状态,如果调用别的类的方法,且该方法依赖于那个类的load方法进行初始化设置,那么必须确保那个类的load方法已经调用了,比如demo中的这段代码,打印出的字符串就为null:

// In Child.m
+ (void)load {
    NSLog(@"Load Class Child");

    Other *other = [Other new];
    [other originalFunc];

    // 如果不先调用other的load,下面这行代码就无效,打印出null
    [Other printName];
}

load方法的调用顺序其实有迹可循,我们看到demo的项目设置如下:

7F1B0C74BB20EB4DD7F68956D93E1D98.jpg

在Compile Sources中,文件的排放顺序就是其装载顺序,自然也就是load方法调用的顺序。这一点也证明了load方法中会自动调用父类的方法,因为在demo的输出结果中,Parent的load方法先于Child调用,而它的装载顺序其实在Child之后。

虽然在这种简单情况下我们可以辨别出各个类的load方法调用的顺序,但永远不要依赖这个顺序完成你的代码逻辑。一方面,这在后期的开发中极容易导致错误,另一方面,你实际上并不需要这么做

使用场景

由于调用load方法时的环境很不安全, 我们应该尽量减少load方法的逻辑. 另外一个原因是load方法是线程安全的, 它内部使用了锁, 所以我们应该避免线程阻塞在load方法中.
常用的使用场景是在load方法中实现Method Swizzle:

+ (void)load {
    Method originalFunc = class_getInstanceMethod([self class], @selector(originalFunc));
    Method swizzledFunc = class_getInstanceMethod([self class], @selector(swizzledFunc));

    method_exchangeImplementations(originalFunc, swizzledFunc);
}
上一篇下一篇

猜你喜欢

热点阅读