[iOS] 基础学习 load和initialize的区别

144 阅读2分钟

官方链接:

load: developer.apple.com/documentati…

initialize: developer.apple.com/documentati…

调用方式的区别

load:根据函数地址直接调用

initialize:通过消息发送调用。

调用时机的区别

load: The load message is sent to classes and categories that are both dynamically loaded and statically linked, but only if the newly loaded class or category implements a method that can respond.

当一个类或分类被加载和链接时,如果其实现了load函数,则以函数形式执行。

initialize:The runtime sends initialize() to each class in a program just before the class, or any class that inherits from it, is sent its first message from within the program. Superclasses receive this message before their subclasses.

当一个类(及其子类)第一次收到消息时,它会以消息形式执行initialize()

调用方式的区别

load:

  • A class’s +load method is called after all of its superclasses’ +load methods.
  • A category +load method is called after the class’s own +load method.
  • 子类会先执行父类的load函数,子类未实现则不调用。
  • 分类会先执行类的load函数,再执行全部分类的load函数。

initialize:

The superclass implementation may be called multiple times if subclasses do not implement initialize()—the runtime will call the inherited implementation—or if subclasses explicitly call [super initialize]. If you want to protect yourself from being run multiple times, you can structure your implementation along these lines:

+ (void)initialize { 
    if (self == [ClassName self]) { 
        // ... do the initialization ... 
    }
}
  • 如果子类和父类都实现了initialize(),则会先执行父类的,再执行子类的。
  • 如果子类没有实现initialize(),会执行父类的,父类的initialize()可能被执行多次。
  • 分类实现的initialize()会覆盖类的实现。

使用场景

load:

  • 交换两个方法的实现
+(void)load {
    
    static dispatch_once_t oneToken;

    dispatch_once(&oneToken, ^{

           Method imageNamed = class_getClassMethod(self,@selector(imageNamed:));
    Method mkeImageNamed =class_getClassMethod(self,@selector(swizze_imageNamed:));
    method_exchangeImplementations(imageNamed, mkeImageNamed);
   
   });
}

+ (instancetype)swizze_imageNamed:(NSString*)name {
    
    //这个时候swizze_imageNamed已经和imageNamed交换imp,所以当你在调用swizze_imageNamed时候其实就是调用imageNamed
     UIImage * image;
    if( IS_IPHONE ){
        // iphone处理
        UIImage * image =  [self swizze_imageNamed:name];
        if (image != nil) {
            return image;
        } else {
            return nil;
        }
    } else {
        // ipad处理,_ipad是自己定义,~ipad是系统自己自定义。
        UIImage *image = [self swizze_imageNamed:[NSString stringWithFormat:@"%@_ipad",name]];
        if (image != nil) {
            return image;
        }else {
            image = [self swizze_imageNamed:name];
            return image;
        }
}

initialize:

  • 主要用来对一些不方便在编译期初始化的对象进行赋值。
// In Person.m
// int类型可以在编译期赋值
static int someNumber = 0; 
static NSMutableArray *someArray;
+ (void)initialize {
    if (self == [Person class]) {
        // 不方便编译期复制的对象在这里赋值
        someArray = [[NSMutableArray alloc] init];
    }
}

补充文档

www.jianshu.com/p/c52d0b6ee…

www.jianshu.com/p/ffdefa76e…

juejin.cn/post/698466…

blog.csdn.net/weixin_3863…

juejin.cn/post/710083…