美文网首页
Swift5.1学习随笔之内存管理

Swift5.1学习随笔之内存管理

作者: SAW_ | 来源:发表于2020-05-14 16:57 被阅读0次

OC一样,swift也是采取基于引用计数的ARC内存管理方案(针对堆空间)

swift中的ARC3种引用:

  • 强引用:默认都是强引用
  • 弱引用:通过weak定义弱引用
    1. 必须是可选类型的var,因为实例销毁后,ARC会自动将弱引用设置为nil
    2. ARC自动给弱引用设置nil时,不会触发属性观察器
  • 无主引用:通过unowned定义无主引用
    1. 不会产生强引用,非可选类型,实例销毁后仍然储存着实例的内存地址(类似OC中的unsafe_unretained
    2. 试图在实例销毁后访问无主引用,会产生运行时错误(野指针)

weakunowned的使用限制
  • weakunowned只能用在类实例上面
protocol Livable: AnyObject { }
class Person { }

weak var p0: Person?
weak var p1: AnyObject?
weak var p2: Livable? //因为Livable协议遵守AnyObject,所以它只能被类遵守

unowned var p10: Person?
unowned var p11: AnyObject?
unowned var p12: Livable?

Autoreleasepool自动释放池

在需要缓解内存压力的地方,使用autoreleasepool

autoreleasepool {
    print("kkkk")
}

循环引用
  • weakunowned都能解决循环引用的问题,unowned要比weak少一些性能消耗
    1. 在生命周期中可能会变成nil的使用weak
    2. 初始化赋值之后再也不会变成nil的,建议使用unowned

闭包的循环引用
  • 闭包表达式默认会对用到的外层对象产生额外的强引用(对外层对象进行了retain操作)
  • 下面代码会产生循环引用,导致Person对象无法释放(deinit无调用)
class Person {
    var fn: (() -> ())?
    func run() { print("Person run") }
    deinit { print("Person deinit") }
}
func test() {
    let p = Person()
    p.fn = { p.run() }
}
test()

通过汇编可以看到,进行了retain操作,导致计数器+1,最终release之后,计数器还是1Person对象没有释放:


尝试注释掉p.fn = { p.run() }这行调用,再看下断点汇编:这时候计算器已经是0了,Person对象被销毁

因为闭包表达式用到了外面的对象,产生了强引用,导致无法释放对象。
  • 在闭包表达式的捕获列表声明weak或者unowned引用,解决循环引用问题
func test() {
    let p = Person()
    p.fn = {
        [weak p] in
        p?.run()
    }
}
test()
p.fn = {
     [unowned p] in
     p.run()
}

甚至可以自定义名称:

p.fn = {
      [weak wp = p, unowned up = p, a = 10 + 20] in
      wp?.run()
}
  • 如果想在定义闭包属性的同时引用self,这个闭包必须是lazy的(因为在实例初始化完毕之后才能引用self
class Person {
    lazy var fn: (() -> ()) = {
        [weak self] in
        self?.run()
    }
    func run() { print("Person run") }
    deinit { print("Person deinit") }
}
func test() {
    var p = Person()
    p.fn()
}
test()
  • 如果lazy属性是闭包调用的结果,那么不用考虑循环引用问题(因为闭包调用后,闭包的生命周期就结束了)
class Person {
    var age: Int = 0
    lazy var getAge: Int = {
        self.age
    }()
    deinit { print("Person deinit") }
}

相关文章

网友评论

      本文标题:Swift5.1学习随笔之内存管理

      本文链接:https://www.haomeiwen.com/subject/qlmtohtx.html