Swift - 内存管理

作者: aven_kang | 来源:发表于2022-04-24 12:09 被阅读0次
跟OC一样,Swift也是采用基于引用计数的ARC内存管理方案(针对堆空间)

Swfit的ARC中有三种引用

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

weak、unowned的使用限制

只能使用在类实例上面
protocol Liveable : AnyObject {}
class Person {}

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

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

循环引用

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

在生命周期中可能变成nil的使用weak
初始化赋值后再也不会变为nil的使用unowned


截屏2022-03-03 下午4.12.27.png

闭包的循环引用

class blockTest {
    
    var fn: (() -> ())?
    func run(){
        print("test")
        
    }
    deinit {
        print("deinit")
    }
}

上述代码中,我们定义了一个类,带有一个block,我们在调用的时候

var b = blockTest()
      b.fn = {
          b.run()
        }

会发现blockTest这个类的deinit这个方法并为执行,说明发生了循环引用
这需要我们在闭包里面加上这句

 var b = blockTest()
 b.fn = {
      [weak b] in
      b?.run()
 }
// [weak b] 把捕获的这个b置为弱引用
截屏2022-03-03 下午4.26.16.png
如果想在定义闭包属性的同时引用self,这个闭包必须是lazy,因为在实例初始化完毕之后才能引用self
class test2 {
    
    lazy var fn:(()->()) = {
        [weak self]
        self.run()
        
    }
    func run() {
        print("run")
    }
    deinit {
        print("test2 deinit")
    }
}

逃逸闭包与非逃逸闭包

截屏2022-03-03 下午5.32.31.png
typealias Fn = ()->()

class Person {
    
    var fn:Fn
    init(fn:@escaping Fn){
        self.fn = fn
    }
    
    func run(){
        
        DispatchQueue.global().async {
            self.fn()
        }
    }
    deinit {
        print("hah deinit")
    }
}
 let person = Person(fn: {        
     print("我终于要执行了")
 })
        
 person.run()
这个就是典型的逃逸闭包,闭包在赋值后并未直接调用,有位可能在未来的某个时刻调用

逃逸闭包不可以捕获inout参数

func other1(_ fn:Fn) {
    
    fn()
    
}

func other2(_ fn: @escaping Fn) {
    
    fn()
    
}

func test(value: inout Int) -> Fn {
    
    
    other1 {
        value += 1
    }
    
    other2 {
        value += 1
    }
    
    func plus(){
        value += 1
    }
    
    return plus
}

如下图


截屏2022-03-04 下午4.13.46.png
Escaping closure captures 'inout' parameter 'value'

会报错

相关文章

  • 每天学一点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/stcurrtx.html