iOS 开发中,+load 和 +initialize 作用和区别

856 阅读2分钟

在 iOS 开发中,+load 和 +initialize 是 Objective-C 中用于类初始化的两个方法,它们在调用时机、用途和特性上有显著区别。以下是详细说明及代码示例:


一、+load 和 +initialize 的区别

特性+load+initialize
调用时机类或分类被加载到运行时(main 函数前)类第一次收到消息时(如方法调用或实例化)
调用次数每个类、分类的 +load 都会被调用一次每个类仅调用一次(包括父类)
自动父类调用父类 +load 在子类之前调用父类 +initialize 在子类之前调用(若未初始化)
分类处理类和分类的 +load 都会被调用分类中的 +initialize 会覆盖原类的实现
线程安全非线程安全(需自行处理)线程安全(运行时自动加锁)
依赖关系可能触发其他类的 +load 提前加载依赖类已加载完成

二、方法作用

  1. +load

    • 用于在类或分类加载时执行一次性代码(如注册类、方法交换)。
    • 不依赖其他类的初始化,但需谨慎处理复杂逻辑(此时其他类可能未加载)。
  2. +initialize

    • 用于类首次使用前的初始化(如设置静态变量、配置单例)。
    • 运行时确保父类先初始化,适合处理类级别的依赖关系。

三、Objective-C 示例

1. +load 示例

// 父类
@interface ParentClass : NSObject
@end

@implementation ParentClass
+ (void)load {
    NSLog(@"ParentClass +load");
}
@end

// 子类
@interface ChildClass : ParentClass
@end

@implementation ChildClass
+ (void)load {
    NSLog(@"ChildClass +load");
}
@end

// 分类
@implementation ChildClass (Category)
+ (void)load {
    NSLog(@"ChildClass(Category) +load");
}
@end

输出顺序

ParentClass +load
ChildClass +load
ChildClass(Category) +load

2. +initialize 示例

// 父类
@implementation ParentClass
+ (void)initialize {
    if (self == [ParentClass self]) {
        NSLog(@"ParentClass +initialize");
    }
}
@end

// 子类
@implementation ChildClass
+ (void)initialize {
    if (self == [ChildClass self]) {
        NSLog(@"ChildClass +initialize");
    }
}
@end

首次使用子类时输出

ParentClass +initialize  // 若父类未初始化
ChildClass +initialize

四、Swift 示例

Swift 中不推荐使用 +load 和 +initialize(纯 Swift 类无法使用)。但通过 @objc 标记继承自 NSObject 的类可部分支持:

1. +load(Swift 4+ 已废弃,需用 @_silgen_name 模拟,不推荐)

2. +initialize 替代方案

class ParentClass: NSObject {
    override class func initialize() {
        if self == ParentClass.self {
            print("ParentClass initialize")
        }
    }
}

class ChildClass: ParentClass {
    override class func initialize() {
        if self == ChildClass.self {
            print("ChildClass initialize")
        }
    }
}

// 首次使用
_ = ChildClass()

输出

ParentClass initialize
ChildClass initialize

3. Swift 推荐方式:静态属性/懒加载

class MyClass {
    static let initialize: Void = {
        print("MyClass static initializer")
    }()

    init() {
        _ = MyClass.initialize // 触发初始化
    }
}

五、关键总结

  • +load 用于极早期初始化,但需谨慎处理依赖。
  • +initialize 用于类首次使用前的配置,更安全。
  • Swift 中优先使用静态属性、懒加载或 dispatch_once(已废弃,改用静态属性)替代。