美文网首页
iOS基础之Objective-C(五)

iOS基础之Objective-C(五)

作者: SuAdrenine | 来源:发表于2016-12-20 22:20 被阅读15次

    内存管理

    1、内存管理范围:
    需要new或者需要alloc、init等关键字创建的对象类型,对于float,char,double,struct,enum等基本数据类型不需要我们去管理他们的内存。(解释:因为对象类型会放在堆中,而非对象类型会存放在栈中,栈中的数据会被系统自动回收)


    2、堆与栈
    堆:一般由程序员分配与释放,如程序员不释放,当程序结束时,可能由系统回收,分配方式类似于链表;
    栈:由操作系统自动分配与释放,一般用于存放形参,局部变量等值。
    例:

    int main() {
      Person *p = [[Person alloc] init];
    }
    

    其中:p存放在栈中,而Person存放在堆中


    3、引用计数器
    (1)、每一个oc对象都有一个自己的引用计数器
    (2)、他是一个整数,占4个字节
    (3)、含义:对象被引用的次数或者有多少东西正在用这个对象
    (4)、引用计数器为0时,对象占用的内存会被系统回收;大于0时,对象的内存不会被回收,除非程序退出了;任何一个对象,被创建以后,引用计数器为1(如使用new,alloc,copy等创建的对象)。
    (5)、引用计数器常见操作:
    a、retain:引用计数器+1
    b、release:引用计数器-1(仅代表计数器-1,不代表销毁对象
    c、retainCount:获取当前计数器的值


    4、dealloc方法
    (1)、当对象的引用计数器为0,对象即将被销毁时,系统会给对象自动调用delloc方法,通过判断有没有调用dealloc方法就可以判定对象有没有被销毁;
    (2)、dealloc的重写:
    一般在重写的dealloc方法中释放资源,且需要调用[super dealloc],并且是放在重写的dealloc方法中的最后;
    (3)、一般不能直接调用dealloc方法,因为调用了就会释放对象占用的内存,操作不当,会造成野指针。


    5、僵尸对象与野指针
    僵尸对象:如果一个对象已经被释放了,那么称这个对象为僵尸对象
    野指针:指向已被释放的对象(即僵尸对象)的指针,我们称之为野指针。


    6、空指针
    没有指向存储空间的指针(里面存放的是nil,也就是0)
    给空指针发送消息没有反应,但是程序不会报错也不会崩溃
    未避免野指针,在对象被销毁之后,将对象指向的指针变为空指针(在MRC中)

    7、内存管理说明以及retain和assign关键字:
    当A对象想使用B对象时一定要对B对象进行一次retain,这样才能保证A对象存在B对象也存在,换句话说就是,无论什么时候,A对象都可以使用B对象,当A对象release时,一定要对B对象也进行一个release。

    @interface A:NSObject {
      B *_b;
    }
    @end
      
    @implementation
    
    -(void)setB:(B *)b{
      [b retain];
      _b = b;
    }
    
    -(void)delloc {
      [_b release];
      [super delloc];
    }
    @end
    

    为避免发生僵尸对象与野指针的情况,set方法最好改写成以下形式:

    -(void)setB:(B *)b{
      if(b != _b) {
        [_b release];  //原数据释放
        _b = [b retain];  //新数据保存;  retain不但会将引用计数+1还会返回对象本身
      }
    }
    

    但是如果每个属性都要这么写一遍,将会非常繁琐,所以我们在声明属性的时候可以声明成这样:

    @property (retain) B *b;
    

    此时我们可以不用自己去实现setter和getter方法,他会自动将属性实现成类似上面的方法。
    而asign不具备管理对象的能力,只能适用于基本数据类型,所以他说实现的将会没有release和retain的getter和setter方法,如下所示:

    @property (retain) NSInteger *num;
    //实现的setter方法如下所示
    -(void)setNum:(NSInteger)num {
      _num = num;
    }
    

    总结:assign不会帮我们生成具备内存管理的setter和getter方法,只会生成默认的方法,如果在@property后面什么都不写,则会将其视为assign;而retain会帮我们生成具备内存管理的setter和getter方法。

    8、atomic与nonatomic:
    atomic:线程安全,但是性能很低
    nonatomic:线程不安全,但是性能相对会高很多

    9、MRC与ARC
    MRC(手动管理内存):在MRC的内存管理模式下,与对变量的管理相关的方法有:retain,release和autorelease。retain和release方法操作的是引用记数,当引用记数为零时,便自动释放内存。并且可以用NSAutoreleasePool对象,对加入自动释放池(autorelease调用)的变量进行管理,当drain时回收内存。
    和内存管理相关的方法
    1)alloc 引用计数器自动设为1
    2)retain 引用计数器+1 返回了经过+1以后的当前实例对象
    3)release 引用计数器-1,并不一定是释放
    4)retainCount 获取引用计数器的值
    5)dealloc 当实例对象被销毁之前,系统自动调用。
    一定要调[super dealloc]
    6)autorelease,该方法是将该对象内存的管理放到autoreleasepool中。

    ARC(自动管理内存,Xcode 4.1/iOS5以后的特性),需要注意的是他是编译器特性,编译器帮助我们插入那些内存管理方法,同时他和其他语言的垃圾回收机制也有很大的不同

    对比:
    ARC中强引用的strong,相当于MRC中的retain
    ARC中弱引用的weak,相当于MRC中的assign
    ARC中保存基本数据类型的assign,跟MRC中的assign一样

    PS:在ARC中,保存弱引用不要用assign,assign是用来保存基本数据类型的,如果要保存弱引用,需要使用weak

    相关文章

      网友评论

          本文标题:iOS基础之Objective-C(五)

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