美文网首页
12.iOS中的ARC内存管理机制

12.iOS中的ARC内存管理机制

作者: LynnXYT | 来源:发表于2016-04-18 12:57 被阅读8次

    12.iOS中的ARC内存管理机制

    1. @property 声明属性

    1.1 本质

    使用@property声明属性,编译器可以自动合成实例变量(_属性名)、getter方法和setter方法
    

    1.2 在 @protocol 和 category 中使用 @property

    1. 在protocol中使用property只会生成setter方法和getter方法声明,使用属性的目的是希望遵守协议的对象能实现该属性。

    2. category使用@property,编译器不会自动合成setter方法和getter方法,类别中无法把实现属性所需的实例变量及其存取方法合成出来,而需要在实现文件中使用@dynamic + 属性名; 的方法告诉编译器在运行时添加setter方法和getter方法,或者是直接在类的实现文件中直接添加该属性的setter方法和getter方法。

    1.3 修饰符

    1.3.1 原子性

    • atomic(默认属性):线程保护技术,防止在未写完成的时候被另外一个线程读取,造成数据错误,这种机制耗费系统资源的。

    • noatomic:访问器只是简单返回这个值,访问速度快。

    1.3.3 读写权限

    • readwrite(读写):同时生成读写方法

    • readonly(只读):只生成getter方法

    1.3.4 内存管理

    这些内存管理的属性只影响设置方法——setter方法

    • assign:设置方法只会针对基本的数据类型进行简单的赋值操作

    • strong:strong类型的属性定义了一种“拥有的关系”,当这种属性设置新值时,会先保留新值,再释放旧值,然后将新值设置给该属性

    • weak:定义了属性间的非拥有的关系,与强引用不同的是weak弱引用既不保留新值,也不释放旧值,与assign类似,当该属性指向的对象被销毁时,属性值被自动设为nil。

    runtime 如何实现 weak 变量的自动置nil?

    runtime对注册的类,会进行布局,对于weak属性的对象会存入一个hash表中,用weak指向的对象的内存地址作为key,当此对象的引用计数为0的时候会调用dealloc方法,,此时hash表中找到以key为键所对应的那个对象设置为nil。

    • unsafe_unretained:与weak属性类似,不同的是unsafe_unretained属性在进行是方法的时候,并不会将该属性置为nil,而是直接释放,这样就会出现野指针,再向这个属性发送消息时会造成程序因异常而结束。

    • copy:与strong属性类似,但是weak属性并不保留新值,而是拷贝新值的一个副本,并赋给该属性,这样保护了程序的封装性。

    • 方法名:可以在定义属性的时候设置该属性的存取方法名。

    2. ARC的本质

    ARC是编译时的特性,而不是运行时特性,也不是垃圾回收机制。ARC是自动引用计数,是对MRC的改进。

    2.1 ARC下的变量修饰符:

    • __strong:(默认)对应property中的strong修饰符,所有对象只有当没有任何一个强引用指向是,才会被释放。如果需要释放强引用指向的对象时,需要将强引用置为nil。
    • __weak:对应property中的weak修饰符,弱引用不会持有对象,只要对象没有强引用指向,就会在该程序段结束后释放,同时将该变量指向的内存置为空。
    • __autoreleasing:会将使用__autoreleasing修饰的属性放入自动释放池。
    • __unsafe_unretained:与weak的作用类似,没有任何额外的操作,但是在指向对象被释放时依然原原本本地指向原来被释放的对象(所在的内存区域)。所以非常不安全。

    2.2 ARC与block

    1. 在MRC中,block会对进入其作用域内的对象(或被block捕获的指针指向的对象)隐式的添加retain,来保证block可以正确使用该对象。但此时容易出现循环引用的问题,即block引用了该类的实例变量,而该类的实例变量用持有该block,这就需要在block使用该对象之前,用__block修饰符修饰该对象。

      在MRC中使用__block的作用:

      • 说明变量可改。(静态变量和全局变量,实例变量在block中是可以被改变的)
      • 说明指针指向的对象不能做隐式的retain操作。
    2. 在ARC中,没有了retain和release操作,此时使用__ block只影响了变量的可修改属性,被block捕获的强引用还是强引用,依旧会造成循环引用的状况。此时需要使用__weak生成一个弱引用,指向需要在block中使用的强引用:

      ViewController * __weak weakSelf = self;
      //或者
      __weak typeof(self) weakSelf = self;
      
    4. ARC与Toll-Free Bridging

    Toll-Free Bridging是使用户可以方便的使用同一种语法来使用CoreFoundation对象和Objective-C对象。

    1. MRC时,OC对象和CF对象多使用相同的release和retain操作

    2. ARC时,OC对象的内存管理规则改变,而CF对象依然是之前的机制(不支持ARC机制)

    3. 引入ARC后对Toll-Free Bridging的操作加入对应的方法与修饰符,用来指明用哪种规则管理内存,或者说是内存管理权的归属。

      • __bridge(修饰符):只是声明类型转变,但是不做内存管理规则的转变。
      • __bridge_retained(修饰符) 或 CFBridgingRetain(函数):表示将指针类型转变的同时,将内存管理的责任由原来的Objective-C交给Core Foundation来处理,也就是,将ARC转变为MRC。
      • __bridge_transfer(修饰符) 或 CFBridgingRelease(函数):功能和上面的__bridge_retained相反,它表示将管理的责任由Core Foundation转交给Objective-C,即将管理方式由MRC转变为ARC。
    3. MRC手动释放引用计数

    一个new/alloc/retain/copy/muticopy对应一个release和一个autorelease。

    相关文章

      网友评论

          本文标题:12.iOS中的ARC内存管理机制

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