一文精通Swift中strong 、weak和unowned使用以及示例

632 阅读2分钟

在 Swift 中,strongweak 和 unowned 是用于管理引用类型(如类实例)内存的关键字,它们的核心区别在于对引用计数(ARC)的影响和如何处理循环引用。以下是详细总结:


1. 核心区别

关键字引用计数是否可为 nil使用场景
strong增加引用计数否(默认行为)默认所有权关系,需要确保对象存活时使用。
weak不增加引用计数是(自动置 nil避免循环引用,且允许对象为 nil(如委托模式)。
unowned不增加引用计数否(访问已释放对象会崩溃)对象生命周期严格一致时使用(如父子依赖)。

2. 何时使用 unowned

  • 使用场景:当两个对象的生命周期严格绑定,且一个对象的销毁必然导致另一个对象无法存在时。

    • 例如:信用卡(CreditCard)不能独立于客户(Customer)存在,此时 CreditCard 对 Customer 的引用应为 unowned
  • 闭包中的使用:如果闭包和捕获的实例生命周期相同(闭包不会在实例销毁后执行),可用 unowned self

    class MyClass {
        func doSomething() {
            someAsyncTask { [unowned self] in
                self.doSomethingElse() // 假设闭包不会在 self 释放后执行
            }
        }
    }
    

3. 对比示例

循环引用问题

class A {
    var b: B?
}

class B {
    // 强引用会导致循环(ABAvar a: A?
}

解决方案

  • 使用 weak(当引用可为 nil 时):

    class B {
        weak var a: A? // 打破循环
    }
    
  • 使用 unowned(当引用不可为 nil 时):

    class CreditCard {
        unowned let owner: Customer // 信用卡必须有持有者
    }
    

4. 注意事项

  • weak 必须声明为可选类型(var + 可选),因为 ARC 会自动将其置 nil
  • unowned 类似非可选的 weak,但需确保对象不会被提前释放,否则访问会触发运行时错误。
  • 闭包捕获列表:优先用 weak 处理可能延迟执行的闭包,用 unowned 仅当闭包与实例生命周期完全一致。

总结

  • strong:默认行为,用于需要保持对象存活的场景。
  • weak:解决循环引用,允许对象为 nil(如委托、闭包可能延迟执行时)。
  • unowned:解决循环引用,用于对象生命周期严格绑定的场景(需确保不会访问已释放对象)。