美文网首页
Swift 内存管理 ⑮

Swift 内存管理 ⑮

作者: Aliv丶Zz | 来源:发表于2020-08-09 14:09 被阅读0次

  跟OC一样,Swift也是采用基于引用计数的ARC内存管理方案(针对堆空间),Swift中的ARC有三种引用:

  • 强引用(strong reference): 默认情况下都是强引用

  • 若引用(weak reference):通过weak定义弱引用
      必须是可选类型的var,因为实力销毁后,ARC会将自动弱引用置位nil
      ARC自动给弱引用设置为nil时,不会触发属性观察

  • 无主引用(unowned reference):通过unowned定义无主引用
      不会产生强引用,实例销毁后仍然存储着实例的内存地址(类似OC中的 unsafe_unretained)
      试图在实例销毁后访问无主引用,会产生运行时错误(野指针)

1. weak、unowned的使用限制

  • weak、unowned只能用在类实例上面
protocol Livable: AnyObject {}//协议继承AnyObject后只能被类继承
class Person {}

weak var p0 : Person?
weak var p1: AnyObject?
weak var p2: Livable?

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

2. 循环引用

  weak、unowned都能解决循环引用的问题,unowned要比weak 少一些性能消耗

  • 在生命周期中有可能变为nil的使用 weak
  • 初始化赋值之后,再也不会变为nil的使用unowned
闭包的循环引用:
  • 闭包表达式默认会对用到的外层对象产生额外的强引用(对外层对象进行returen操作)
class Person {
    var fn: (() -> ())?
    
    func run()  {
        print("person run")
    }

    deinit {
        print("person deinit")
    }
    
}
func tt()  {
    print("tt")
}
func test()  {
    var p = Person()
    p.fn = {p.run()}
}

test()

注意:这里并不会看到打印person deinit。因为 var p = Person(),Person对象p强引用fn闭包。当执行完 p.fn = {p.run()}时,闭包又强引用Person对象,造成循环引用

在闭包表达式的捕获列表声明weak或unowned引用,可解决循环引用问题
func test()  {
    var p = Person()
    p.fn = {
        [weak p] in
        p?.run()
    }
}

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

    lazy var getAge: Int = {
        self.age
    }()
}

3. 内存访问冲突

内存访问冲突会在两个访问满足下列条件时发生:
  1. 至少一个是写入操作
  2. 他们访问的是同一块内存
  3. 他们的访问时间重叠(比如在同一个函数中)
内存访问冲突.png

解决方案:


解决方案.png
如果下面的条件满足,就说明重叠访问结构体的属性时安全的:
  1. 你只访问实例存储属性,不是计算属性或者类属性
  2. 结构体时局部变量而非全局变量
  3. 结构体要么没有被闭包捕获要么纸杯费逃逸闭包捕获

相关文章

  • 每天学一点Swift----面向对象下(十)

    十九. Swift内存管理 1. Swift提供了强大的内存管理机制:Swift通过自动引用计数(ARC)可以很好...

  • Swift--内存管理

    Swift内存管理概述 强引用循环 打破强引用循环 闭包中的强引用循环 Swift内存管理概述 Swift中的AR...

  • swift内存管理

    Swift使用自动引用计数(ARC)机制来处理内存。通常情况下,Swift内存管理机制会自动管理内存,无须我们考虑...

  • Swift使用自动引用计数

    Swift使用自动引用计数(ARC)机制来处理内存。通常情况下,Swift内存管理机制会自动管理内存,无须我们考虑...

  • Swift 内存管理

    Swift 内存管理 [TOC] 前言 本文将介绍一下Swift中的内存管理,关于内存的一些基础知识可以参考我以前...

  • Swift底层原理-内存管理

    Swift底层原理-内存管理 Swift语言延续了和Objective-C语言一样的思路进行内存管理,都是采用引用...

  • Swift-内存管理,指针

    内存管理 Swift采用引用计数的ARC内存管理方案(堆空间) Swift的ARC中有3钟引用强引用弱引用(wea...

  • 内存管理

    Swift内存管理:管理引用类型的内存, 不会管理值类型, 值类型不需要管理内存管理原则: 当没有任何强引用指向对...

  • Swift内存管理&闭包使用

    一、内存管理 1、跟OC一样,Swift也是采取基于引用计数的ARC内存管理方案(针对堆空间) 2、Swift的A...

  • 内存管理

    内存管理 跟OC一样,Swift也是采取基于引用计数的ARC内存管理方案(针对堆空间) Swift的ARC中有3种...

网友评论

      本文标题:Swift 内存管理 ⑮

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