在 iOS 开发中,+load 和 +initialize 是 Objective-C 中用于类初始化的两个方法,它们在调用时机、用途和特性上有显著区别。以下是详细说明及代码示例:
一、+load 和 +initialize 的区别
| 特性 | +load | +initialize |
|---|---|---|
| 调用时机 | 类或分类被加载到运行时(main 函数前) | 类第一次收到消息时(如方法调用或实例化) |
| 调用次数 | 每个类、分类的 +load 都会被调用一次 | 每个类仅调用一次(包括父类) |
| 自动父类调用 | 父类 +load 在子类之前调用 | 父类 +initialize 在子类之前调用(若未初始化) |
| 分类处理 | 类和分类的 +load 都会被调用 | 分类中的 +initialize 会覆盖原类的实现 |
| 线程安全 | 非线程安全(需自行处理) | 线程安全(运行时自动加锁) |
| 依赖关系 | 可能触发其他类的 +load 提前加载 | 依赖类已加载完成 |
二、方法作用
-
+load- 用于在类或分类加载时执行一次性代码(如注册类、方法交换)。
- 不依赖其他类的初始化,但需谨慎处理复杂逻辑(此时其他类可能未加载)。
-
+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(已废弃,改用静态属性)替代。