您的位置:首页 > 移动开发 > IOS开发

iOS内存管理与ARC,及Property介绍

2015-08-28 15:02 323 查看
作为直接学习面向对象的我来说,刚开始对内存管理完全没有概念,所以这里介绍一下自己学习ARC进行内存管理的心得。

首先介绍两个基本概念:

栈(stack)和堆(heap)

堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。

栈:先进先出;堆,后进先出。

在iOS中,当执行方法的时候,会分配一部分内存,这部分内存叫做frame,frame会被放在栈上。当方法结束调用后,frame会出栈,内存被销毁。

而堆,则是Objecti-C中对象存在的地方,通过使用指针来确定对象存储在堆的位置。由于iOS应用在运行中,对象会不断产生,而内存资源是有限的,所以必须释放一部分对象的内存。如果自己手动的释放内存,头都大了,幸好有ARC来解决这些问题。

ARC与内存管理

ARC代表自动引用计数,在之前苹果使用人工引用计数,需要release和retain很多object,有很多不便,后来苹果搞了个开源的项目Clang static analyzer来查找内存管理的bug,并集成到Xcode中,最终发展为ARC。

指针变量和对象归属(Object Ownership)

指针变量指示它们指向的对象的归属。归属有两种形式:

1.方法中的局部变量指向对象,那么我们说这个变量拥有(own)被指向的对象

2.对象中的实例变量指向另一个对象,那我们说对象拥有被指向的对象

对象归属的概念可以来决定是否销毁一个对象,来重复使用它的内存。由以下两种方式决定是否被销毁:

1.没有所有者(owners)的对象会被销毁。如果没被销毁,那么叫做内存泄露。

2.拥有一个或以上所有者的对象不会被销毁。如果一个对象被销毁,但另外的对象仍然指向它那么应用会崩溃,销毁这样的对象叫做premature deallocation,或者叫悬浮指针。

对象失去所有者(lose ownership)的方式共有四种:

1.指向对象的变量变化

2.指向对象的变量被设为空(nil)

3.对象所有者自主销毁(比如栈里面的方法执行完毕后,那么frame拥有的对象就会出栈并被销毁)

4.集合中的对象,比如数组,被移除

所属关系链

对象会拥有对象,那么单个对象的销毁会导致一些列的失去所有者,对象销毁和内存释放。

强指针和弱指针

指针变量指向对象时,变量是对象的所有者,那么就是强指针;反之,则是弱指针。

弱指针在防止循环引用(retain cycle)十分有效。当两个以上的对象互相指向自己,就会发生循环引用。

比如以下代码:

@interface RCItem:NSObject:

{

RCItem *_containedItem;RCItem *_container;}

在.m文件中,设置访问器:- (void)setContainedItem:(RCItem *)item{_containedItem = item;item.container = self;}这样的话假设实例化RCItem类并设置两个对象,RCItem *backpack;RCItem *contents, 并设置backpack.containedItem = contents.那么这两个对象就会相互引用,最终导致别的方法也不能访问他们,也不会被销毁导致内存泄露。解决的办法一般是采用“父子关系”,在这个例子中把container当做父类,并把它设为弱指针,那么子类的对象就不能拥有它:__weak
RCItem *_container;

属性(Property)和属性特征(Property attributes)

默认情况下,设置属性会产生实例变量,存、取方法,共三个东东。

@property (nonatomic, readwrite,strong) NSString *string;

第一个是多线程的特性,默认的是natomic,然而大多数的ios程序使用nonatomic;

第二个是读写特性,readwrite(读写)和readonly(只读),后者不可以对属性设值;

第三个是内存管理特性,strong, weak, copy , unsafe_unretained(assign)。

对于不指向对象的属性比如int型,就是unsafe_unretained,以前叫assign;

当属性指向有可变子类的类的实例的时候,比如NSArray,应当使用copy(产生对对象的强引用指针),来创建副本防止原来的对象被未知的的程序改变。当然在iOS机制里面,为了避免无用的copy,不变对象只会返回原始对象的指针,而不会产生另一个副本。

属性合成(Property Synthesis)

在类借口中声明属性只会产生存取方法,为了使他自动生成实例变量,它必须被显式或隐式synthesized。

显式合成:@synthesize name = _name;

左边的一项表示,产生name和setName:方法;右边的表示,这两种方法返回的实例变量用_name表示。

当然你也可以这样 @synthesize name;它和 @synthesize name = name;是一样的,表示返回的实例变量用name表示。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息