黑马程序员——ios知识整理——MRC手动内存管理

来源:互联网 发布:动漫源码 编辑:程序博客网 时间:2024/04/29 10:50

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


(以下均为个人理解,手动输入,如有错误,请您留言更正,谢谢)

一、OC中内存管理的简单概述:


OC中的每个对象都存在自己的引用计数器,代表对象拥有的所有者的个数或者说是被引用的次数,当引用计数器的值为0时(如果对象不为nil),对象会被销毁,将不可以继续使用。

引用计数器,是判断对象是否被回收的唯一标准。


二、引用计数器的操作:


retain   引用计数器+1

release 引用计数器-1

retainCount 获取引用计数器的值


三、一个对象被释放的时候,会调用对象方法dealloc,dealloc方法是NSObject的,一般都会对其进行重写,重写时调用[super dealloc],确保对象被销毁。


四、内存管理模式:MRC手动内存管理、ARC自动内存管理


五、手动内存管理的原则:


对象如果不再使用,就需要回收其空间,防止内存泄露

内存管理的范围,是继承了NSObject的所有对象

内存管理不涉及基本数据类型,如int、float、double、enum、struct、char等

1.谁创建,谁release 2.谁retain,谁release


下面是一段MRC下手动内存管理的简单代码:


需要注意的是,xcode默认为ARC模式,需要将其关闭,箭头处选择no

<pre name="code" class="objc">#import <Foundation/Foundation.h>//创建一个Person类@interface Person : NSObject{        int _age;    float _weight;    }@end@implementation Person//重写dealloc-(void)dealloc{        NSLog(@"对象p已经被销毁");    [super dealloc];    }@endint main(int argc, const char * argv[]) {    @autoreleasepool {        //实例化对象p        Person *p =[Person new];        //打印p的retainCount        NSLog(@"%ld",p.retainCount);        //让p retain一次        [p retain];        NSLog(@"%ld",p.retainCount);        //谁retain 谁release        [p release];         NSLog(@"%ld",p.retainCount);        //谁创建 谁release        [p release];        //此处retainCount为0 系统自动调用dealloc方法 我们在实现中进行重写,查看其调用情况    }    return 0;}

运行结果:(运行结果中时间被去掉)

<div style="text-align: left;"><pre name="code" class="objc"> MRC[779:303] 1 MRC[779:303] 2 MRC[779:303] 1 MRC[779:303] 对象p已经被销毁

六、单个对象的野指针问题:

在以上所写代码的最后一行,再次使用p指针,就会造成野指针问题,此时的p也称僵尸对象。因为当对象的retainCount为0时,系统将对象进行dealloc,内存被回收后,内存中的内容并不会被清空,只是系统层面的清空,并没有清空物理内存。所以如果不开启僵尸对象监测的情况下,仍然可以在对象release后进行访问。

xcode中提供僵尸对象的检测,方法如下图所示:

开启僵尸对象监测后,系统会对僵尸对象的操作进行提示,代码及注释如下:

<div style="text-align: left;"><pre name="code" class="objc">int main(int argc, const char * argv[]) {    @autoreleasepool {        //实例化对象p        Person *p =[Person new];        //打印p的retainCount        NSLog(@"%ld",p.retainCount);        //让p retain一次        [p retain];        NSLog(@"%ld",p.retainCount);        //谁retain 谁release        [p release];         NSLog(@"%ld",p.retainCount);        //谁创建 谁release        [p release];        //此处retainCount为0 系统自动调用dealloc方法 我们在实现中进行重写,查看其调用情况        /*         我们的对象已经被销毁,但是p做为一个局部变量,仍未销毁,再次调用可以使用.这时的指针p,就是一个野指针,为了防止错误的调用,可以开启僵尸对象检测,进行提示         */        NSLog(@"%ld",p.retainCount);    }    return 0;}


运行结果如下:

 MRC[804:303] 1 MRC[804:303] 2 MRC[804:303] 1 MRC[804:303] 对象p已经被销毁 MRC[804:303] *** -[Person retainCount]: message sent to deallocated instance 0x100202000
代码的最后一行会进行提示并报错

为了防止野指针的访问,可以在手动释放后,将对象赋值为空指针: p = nil ;

七、set方法的内存管理
<pre name="code" class="objc">//基本数据类型:直接赋值
//int float double long struct enum 数据类型
-(void)setAge:(int)age{_age=age; }
//OC对象类型
-(void)setCar:(Car *)car{//1.先判断是不是新传进来的对象<span style="white-space:pre"></span>If(car!=_car){//2.对旧对象做一次release<span style="white-space:pre"></span>[_car release];//若没有旧对象,则没有影响 
//3.对新对象做一次retain<span style="white-space:pre"></span>_car=[car retain];}
}


八、@property

xcode对于@property进行了增强,@property可以根据参数的设置,直接调用相应的方法,不必再手动进行方法的重写,提高效率
其中最常用的方法为
@property(nonatomic,retain) 生成get、set方法时,对set方法进行重写,先release原对象,再retain新值
@property(nonatomic,assgin)声称的set方法,对于基本数据类型进行直接赋值
其中的nonatomic是高性能模式,默认为atomic,所以一般需要我们手动的进行开启该模式

九、autorelease pool 自动释放池的使用

基本用法

(1)会将对象放到一个自动释放池中

(2)当自动释放池被销毁时,会对池子里的所有对象做一次release

(3)会返回对象本身

(4)调用完autorelease方法后,对象的计数器不受影响




0 0
原创粉丝点击