美文网首页
OC的load和initialize方法分析

OC的load和initialize方法分析

作者: 芝麻酱的简书 | 来源:发表于2019-01-15 15:08 被阅读0次

    load

    + (void)load函数调用特点如下:
    当类被引用进项目的时候就会执行load函数(在main函数开始执行之前),与这个类是否被用到无关,每个类的load函数只会自动调用一次.由于load函数是系统自动加载的,因此不需要调用父类的load函数,否则父类的load函数会多次执行。

    • 当父类和子类都实现load函数时,父类的load方法执行顺序要优先子类
    • 无论父类还是子类,只要实现了load方法就会调用;否则不会调用
    • 类中的load方法执行顺序要优先于类别(Category)
    • 当有多个类别(Category)都实现了load方法,这几个load方法都会执行,但执行顺序不确定(其执行顺序与类别在Compile Sources中出现的顺序一致)

    由于调用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);
    }
    

    initialize

    + (void)initialize函数调用特点如下:
    initialize在类或者其子类的第一个方法被调用前调用。即使类文件被引用进项目,但是没有使用,initialize不会被调用。由于是系统自动调用,也不需要再调用 [super initialize] ,否则父类的initialize会被多次执行。假如这个类放到代码中,而这段代码并没有被执行,这个函数是不会被执行的。

    • 父类的initialize方法会比子类先执行
    • 当子类未实现initialize方法时,会调用父类initialize方法,子类实现initialize方法时,会覆盖父类initialize方法.
    • 当有多个Category都实现了initialize方法,会覆盖类中的方法,只执行一个(会执行Compile Sources 列表中最后一个Category 的initialize方法)

    由于无论子类实现实现了initialize方法,父类方法都会被执行,就导致父类多次调用该方法,所以正确的使用姿势是:

    // In Parent.m
    + (void)initialize {
        if (self == [Parent class]) {
           ...
        }
    }
    

    总结

    • load和initialize方法都会在实例化对象之前调用,以main函数为分水岭,前者在main函数之前调用,后者在之后调用。这两个方法会被自动调用,不能手动调用它们。
    • load和initialize方法都不用显示的调用父类的方法而是自动调用,即使子类没有initialize方法也会调用父类的方法,而load方法则不会调用父类。
    • load方法通常用来进行Method Swizzle,initialize方法一般用于初始化全局变量或静态变量。
    • load和initialize方法内部使用了锁,因此它们是线程安全的。实现时要尽可能保持简单,避免阻塞线程,不要再使用锁。

    相关文章

      网友评论

          本文标题:OC的load和initialize方法分析

          本文链接:https://www.haomeiwen.com/subject/nvrydqtx.html