You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift闭包中deinit时机疑问:为何Increment实例提前销毁?

链式调用下Swift实例提前销毁的原因分析

下面两段Swift代码的执行结果存在明显差异:

链式调用写法

class Increment {
    var number = 0

    init(){
        print(#function)
    }
    deinit {
        print(#function)
    }
    // let incrementNumber would give an error — 1
    lazy var incrementNumber: (Int) -> () = { [weak self] value in
        self?.number += value
        print(self?.number)
    }
}

do {
    let increment = Increment().incrementNumber(3)
}
// 输出:
// init()
// deinit
// nil

拆分调用写法

当把代码拆分成以下形式时,闭包执行阶段self仍处于存活状态:

let increment = Increment()
increment.incrementNumber(3)
// 输出:
// init()
// Optional(3)
// deinit

差异原因

链式调用Increment().incrementNumber(3)的执行逻辑是:

  • 首先创建Increment的临时实例,但这个实例没有被任何强引用变量持有;
  • 接着访问实例的lazy属性incrementNumber,触发闭包初始化并获取到闭包对象;
  • 此时临时实例已经没有任何强引用,Swift的ARC(自动引用计数)会立刻销毁这个实例,调用deinit;
  • 最后执行闭包时,[weak self]已经变成nil,自然无法修改number,输出nil。

而拆分写法的逻辑是:

  • let increment = Increment()将实例赋值给变量increment,这个变量持有了实例的强引用;
  • 调用increment.incrementNumber(3)时,实例仍被强引用持有,不会被销毁;
  • 闭包执行时self有效,能正常修改number并输出Optional(3);
  • 只有当increment超出作用域后,实例才会失去强引用,被销毁并调用deinit。

核心差异点在于链式调用中的临时实例没有被强引用持有,导致在闭包执行前就被ARC回收了。

内容的提问来源于stack exchange,提问作者alphabetF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 21:40:39