Swift类中常量属性为何被初始化两次?如何修复?
Swift与OC混合开发中实例初始化重复创建对象及内存泄漏问题
问题代码
// ViewController.m @interface ViewController () @property (nonatomic, strong) MyModel *model; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.model = [[MyModel alloc] initWithIntValue:10]; }
// MyModel.swift fileprivate class SomeProperty { init() { print("SomeProperty init") } } class MyModel: BaseModel { private let property = SomeProperty() }
// BaseModel.h @interface BaseModel : NSObject - (instancetype)initWithIntValue:(int)intValue; - (instancetype)initWithIntValue:(int)intValue doubleValue:(double)doubleValue; @end
// BaseModel.m @implementation BaseModel - (instancetype)initWithIntValue:(int)intValue doubleValue:(double)doubleValue { if (self = [super init]) { } return self; } - (instancetype)initWithIntValue:(int)intValue { return [self initWithIntValue:intValue doubleValue:0]; } @end
问题现象
初始化MyModel实例时,控制台两次打印"SomeProperty init",Debug Memory Graph显示SomeProperty对象存在内存泄漏。
原因分析
Swift类继承OC类时,OC的初始化方法链会触发Swift的初始化逻辑两次:
- 调用
[[MyModel alloc] initWithIntValue:10]时,OC的initWithIntValue:会调用initWithIntValue:doubleValue:; - Swift子类在OC初始化流程中,会先隐式触发一次默认初始化(创建
property属性),随后在self = [super init]完成后,又会触发一次Swift的初始化逻辑,导致SomeProperty被实例化两次; - 第一次创建的
SomeProperty对象因后续初始化覆盖了实例引用,无法被ARC回收,从而造成内存泄漏。
修复方案
核心是让Swift子类显式实现匹配OC基类的指定初始化器,避免隐式默认初始化被重复触发:
修改MyModel.swift代码:
fileprivate class SomeProperty { init() { print("SomeProperty init") } } class MyModel: BaseModel { private let property: SomeProperty // 显式实现匹配OC的指定初始化器 @objc init(intValue: Int) { // 先完成自身属性初始化 self.property = SomeProperty() // 再调用父类初始化方法 super.init(intValue: intValue) } // 必须实现的编解码初始化器(若不需要可保持fatalError) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
修改后,property只会在显式初始化器中被创建一次,避免了重复实例化和内存泄漏问题。
内容的提问来源于stack exchange,提问作者P. Tsin
相关产品推荐
相关产品推荐

