OC学习--内存管理

【为什么要进行内存管理】

由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继续使用的内存空间,比如回收一些不再使用的对象和变量等。

管理范围:任何继承NSObject的对象,对其他的基本数据类型无效

本质原因是因为对象和其他数据类型在系统中的存储空间不一样,其它局部变量主要存放于栈中,而对象存储于堆中,当代码块结束时这个代码块中涉及的所有局部变量会被回收,指向对象的指针也被回收,此时对象已经没有指针指向,但依然存在于内存中,造成内存泄露。


【内存管理】

内存管理就是确保申请的内存能够得到合理及时的释放

1、忘记释放一个堆空间,称为【内存泄漏】

2、使用已经释放的内存,称为【提前释放】

3、多次释放同一堆空间,称为【重复释放】


【困境】

1、释放一个堆空间,需要确保所有指向该空间的指针都不再使用

2、释放一个堆空间,需要确保指向同一空间的指针只释放一次

3、模块化操作时,哪个模块负责释放将成为巨大的难题

4、多线程操作时,没有办法确定哪个线程最后结束


【解决】

采用类似于聊天室的计数方式。第一个人开始聊天时创建聊天室,并将计数值设置为1。当多一个人加入聊天室时,将计数值加1;当一个人离开聊天室时,将计数值减1,计数值减到0时释放聊天室。

其实就是确保聊天室中的人数与计数值相等。


【结论】

在创建对象时引用计数默认为1,当多一个指针指向该对象时将计数值加1;当少一个指针指向对象时将计数值减1,计数值减到0时释放对象。

其实就是确保指向对象的指针数等于计数值,每一个OC对象都有自己的引用计数,表示对像被引用的次数,即表示现在有多少东西在使用这个对象。


一、手动内存管理

  Manual Reference Counting,简称MRC

【关闭ARC】 

1、工程 —> gar

2、Yes —> No


【相关操作】

   1、获取对象的引用计数

NSUInteger count = [dog retainCount];


   2、使对象的引用计数加1

//将对象的引用计数加1,并返回该对象的地址

    //平白无故的retain是不允许

    JYDog *dog2 = [dog retain];


   3、使对象的引用计数减1,减到0时释放对象

[dog2 release];

dog2=nil;//该语句经常被省略,但是要确保dog2以后不再使用。


   4、析构方法

//析构方法,在对象释放时自动调用

- (void)dealloc

{

    NSLog(@"dog 对象即将释放");

    [super dealloc];

}


         当一个对象的引用计数器为0时,那么它将被销毁,其占用的内存被系统回收。

        当对象被销毁时,系统会自动向对象发送一条dealloc消息,一般会重写dealloc方法,在这里释放相关的资源,dealloc就像是对象的临终遗言。一旦重写了dealloc方法就必须调用[super dealloc],并且放在代码块的最后调用(不能直接调用dealloc方法)。

         一旦对象被回收了,那么他所占据的存储空间就不再可用,坚持使用会导致程序崩溃(野指针错误)。


【黄金法则】

1、凡是用alloc/new/retain/copy(开头)/mutableCopy(开头)等创建的对象,都需要调用release/autorelease进行释放。

2、谁写alloc,谁写release;哪个类创建,哪个类释放


【注意事项】

1、对象的子对象需要在析构方法中释放

2、在指针转移时,应先释放就对象,然后指向新对象

3、数组的内存管理,

   

        NSMutableArray *ary = [[NSMutableArray alloc] init];

        NSString *str1 = [[NSString alloc] initWithUTF8String:"123"];

        //将一个对象添加到数组中,会自动retain

        [ary addObject:str1];

        //当数组释放时,会向数组中的每个对象发送一个release消息

        //[ary release];

        [str1 release];

        

        //NSLog(@"str1:%lu", str1.retainCount);

        

        //从数组中获取一个对象,对象并没有retain,在使用时应确保对象没有释放

        //可以获取retain一次

        //建议短时间(数组释放前)内可以不用retain

        NSString *str2 = [ary[0] retain];

        [ary release];

        NSLog(@"str2:%lu", str2.retainCount);

        [str2 release];


4、[[JYClass alloc] init] <==> [JYClass new]

5、(mutable)copy基本上只有在NSString上


【自动释放】

以前不是关键字,是一个类NSAutoreleasePool,可以将需要释放的对象存放在其中(类似于一个数组),等池释放时将其中的对象各释放一次,也叫延迟释放。

现在为了配合ARC改成关键字@autoreleasepool


 【说明】

1、一定要结合自动释放池

2、对象的引用计数不会直接减1,等池释放时才会减1


 【自动释放原则】—— 非用不可的时候

1、类方法创建的对象

2、getter方法中[[_name retain] autorelease]


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值