• Swift中的可选链与内存管理(干货系列)


    干货之前:补充一下可选链(optional chain)

     1 class A {
     2     var p: B?
     3 
     4 }
     5 
     6 class B
     7 {
     8     var p: C?
     9 }
    10 
    11 class C {
    12     func cm() -> String {
    13         print("cm")
    14         return "abc"
    15     }
    16 }
    17 
    18 let insa = A()
    19 let insb = B()
    20 let insc = C()
    21 insa.p = insb
    22 //insa.p = nil
    23 insb.p = insc
    24 
    25 let r = insa.p?.p?.cm()

    解析:此处定义了A,B,C三个类,使其依次关联,最后通过类A实例的属性拿到B实例,依次拿到C实例再调用C的方法。

    注意:1,中间任何一个地方为nil,不报错,但导致整个结果为nil。

    2,如果没有一个地方为nil,整个表达式才正常执行。

    内存管理

    swift中的或者java,c#语言的内存管理,指的就是引用类型对象的管理,也就是对“堆(heap)”里面的对象的管理。

    这三种语言中,值类型不需要进行内存管理,值类型是放在栈里的,程序会自动管理,不需要特别的机制。

    swift中的内存管理技术,叫做arc,自动引用计数(Auto Reference Count) 当对对象的引用计数为0时,立即销毁对象

    这种管理一般会产生两种错误可能

    1.空引用

    2.内存泄露(leak) 某个时候,某些对象分配了内存,但因为某些原因,导致程序结束时,此对象所占的内存没有被回收

    我们可以控制的引用计数的数量 增加的方法 1.声明变量,指向某个对象(直接new或者把别的变量的值赋值给你 )

    减少的方法

    1.f = nil(表示不指向任何东西)

    2.变量一般会运行在函数中,变量本身是存放在栈中的 所以函数结束时,此变量消失

    关于循环引用swift提供了两种方法来解决,

    一种是weak(弱),一种是unowned(未拥有)

    1.weak 可以修饰在可为空(?,!)的属性上

    2.unowned只能修饰在非可为空的属性上。

    循环引用案例

     1 class A {
     2     var p: B?
     3     init() {
     4         print("a********************")
     5     }
     6     deinit {
     7         print("a--------------------")
     8     }
     9 }
    10 
    11 class B{
    12     var p: A?
    13     init() {
    14         print("b********************")
    15     }
    16     deinit {
    17         print("b--------------------")
    18     }
    19 
    20 }
    21 var f1:A? = A()
    22 var f2:B? = B()
    23 //使用这两个类时,可以从控制台看到这两个类已经初始化完毕
    24 //通过f1f2两个对象的属性将这两个类相互关联
    25 f1?.p = f2
    26 f2?.p = f1
    27 //此时再将这两个对象赋值为nil
    28 //f1 = nil
    29 //f2 = nil
    30 //但此时并没有调用类的析构函数
    31 //原因:f1f2这两个对象的属性相互引用了这两个对象
    32 f1?.p = nil
    33 f2?.p = nil
    34 f1 = nil
    35 f2 = nil

    解析:1,此处现将f1f2两对象的属性赋值为nil再将f1f2赋值为nil即代表A,B这两个类完全没有引用,此时才会调用析构函数,回收内存。

    2,以上这种循环引用的问题,对象并没有真正清除常常会导致内存泄漏(leak)

    解决方法一:weak

     1 class C {
     2     var p: D?
     3     init() {
     4         print("c********************")
     5     }
     6     deinit {
     7         print("c--------------------")
     8     }
     9 }
    10 
    11 class D{
    12     weak var p: C?
    13     init() {
    14         print("d********************")
    15     }
    16     deinit {
    17         print("d--------------------")
    18     }
    19     
    20 }
    21 var f3:C? = C()
    22 var f4:D? = D()
    23 f3 = nil
    24 f4 = nil

    此时发现在任何一个循环引用的属性上加上weak关键字,即可解决上述问题

    注意:weak 可以修饰在可为空(?,!)的属性上

    解决方式二:unowned

     1 class E {
     2     var p: F?
     3     init() {
     4         print("e********************")
     5     }
     6     deinit {
     7         print("e--------------------")
     8     }
     9 }
    10 
    11 class F{
    12     unowned var p: E
    13     init(a:E) {
    14         p = a
    15         print("f********************")
    16     }
    17     deinit {
    18         print("f--------------------")
    19     }
    20     
    21 }
    22 var f5:E? = E()
    23 var f6:F? = F(a:f5!)
    24 f5 = nil
    25 f6 = nil

    注意:unowned只能修饰在非可为空的属性上。

  • 相关阅读:
    修改版的jsonView,加入了PHP的反序列化
    CSBlogV2公测发布,欢迎大家下载试用体验.
    C#里使用Oracle提供的Oracle.DataAccess 返回包里的记录集游标,含Oralce里的分页包代码
    用一个示例方法来初始理解ManualResetEvent的用法。
    Head First 设计模式阅读所得:策略模式(Strategy Pattern) 接口的用处(之一)
    延时至调用时获取被反序列化数据的类型的实现
    权限设计中的"依赖颠倒"
    CSCMSV1终于上线内测了[广告贴]
    Windows Service 使用参数安装DEMO,可使用控制台启动方式进行调试,服务安装完后立即启动
    使用assembly.GetExportedTypes();方法时引发动:态程序集中不支持已调用的成员的异常
  • 原文地址:https://www.cnblogs.com/1016882435AIDA/p/6102030.html
Copyright © 2020-2023  润新知