zoukankan      html  css  js  c++  java
  • Swift

    Swift使用自动引用计数(ARC)来管理应用程序的内存使用。在大多是情况下,并不需要考虑内存的管理。当实例不再需要的时候,ARC会自动释放这些实例所使用的内存。

    但ARC并不是绝对安全的。下面两种情况会发生内存泄露。

    1,类实例之间的循环强引用
    两个类实例都有一个强引用指向对方,这样的情况就是强引用循环,从而导致内存泄露。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    class Teacher {
        var tName : String
        var student : Student?
         
        init(name:String){
            tName = name
            println("老师(tName)实例初始化完成")
        }
         
        deinit{
            println("老师(tName)实例反初始化完成")
        }
    }
     
    class Student {
        var sName : String
        var teacher : Teacher?
         
        init(name:String){
            sName = name
            println("学生(sName)实例初始化完成")
        }
         
        deinit{
            println("学生(sName)实例反初始化完成")
        }
    }
     
    //测试开始
    var teacher:Teacher?
    var student:Student?
    teacher = Teacher(name: "李老师")
    student = Student(name: "刘同学")
    teacher!.student = student
    student!.teacher = teacher       
    teacher = nil
    student = nil
     
    //测试结果(deinit未调用,则内存泄露)
    老师李老师实例初始化完成
    学生刘同学实例初始化完成


    解决办法:使用弱引用

    只需要将上述例子Teacher类的student变量加上关键字weak,或者将Student类的teacher变量加上关键字weak。
    当A类中包含有B类的弱引用的实例,同时,B类中存在A的强引用实例时,如果A释放,也不会影响B的释放。但A的内存回收要等到B的实例释放后才可以回收。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    class Teacher {
        var tName : String
        weak var student : Student?
         
        init(name:String){
            tName = name
            println("老师(tName)实例初始化完成")
        }
         
        deinit{
            println("老师(tName)实例反初始化完成")
        }
    }
     
    class Student {
        var sName : String
        var teacher : Teacher?
         
        init(name:String){
            sName = name
            println("学生(sName)实例初始化完成")
        }
         
        deinit{
            println("学生(sName)实例反初始化完成")
        }
    }


    2,闭包引起的循环强引用 

    将一个闭包赋值给类实例的某个属性,并且这个闭包体中又使用了实例,也会发生强引用循环。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    class JsonElement{
        let name:String
        let jValue:String?
         
        lazy var asJson:() -> String = {
            if let text = self.jValue {
                return "(self.name):(text)"
            }else{
                return "text is nil"
            }
        }
         
        init(name:String, text:String){
            self.name = name
            self.jValue = text
            println("初始化闭包")
        }
         
        deinit{
            println("闭包释放")
        }
    }
     
    //开始测试
    var p:JsonElement? = JsonElement(name: "p", text: "hangge.com")
    println(p!.asJson())
    p = nil
     
    //测试结果(deinit未调用,则内存泄露)
    初始化闭包
    p:hangge.com


    解决办法:使用闭包捕获列表

    当闭包和实例之间总是引用对方并且同时释放时,定义闭包捕获列表为无主引用。但捕获引用可能为nil时,定义捕获列表为弱引用。弱引用通常是可选类型,并且在实例释放后被设置为nil。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    class JsonElement{
        let name:String
        let jValue:String?
         
        lazy var asJson:() -> String = {
            [unowned self] in //使用无主引用来解决强引用循环
            if let text = self.jValue {
                return "(self.name):(text)"
            }else{
                return "text is nil"
            }
        }
         
        init(name:String, text:String){
            self.name = name
            self.jValue = text
            println("初始化闭包")
        }
         
        deinit{
            println("闭包释放")
        }
    }
  • 相关阅读:
    学习PetShop3.0(9)工厂的资料
    net程序架构开发
    《解剖PetShop》系列之一
    与数据库相关的名词解释
    asp 导出Excel
    《解剖PetShop》系列之二
    业务模块的设计原则
    《解剖PetShop》系列之三
    JAVA之BigInteger(转)【转】【很好用啊】
    php_mcrypt.dll无法加载解决方法
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4841131.html
Copyright © 2011-2022 走看看