您的位置:首页 > 其它

OC 内存管理

2016-02-17 15:23 363 查看
Object-C 并没有像 C#、java 那样拥有垃圾回收机制,所以OC的内存管理需要开发人员手动维护。

一、引用计数器 Automatic Reference Counting

在Xcode4.2及以后的版本引入了ARC机制,可以为你的代码自动带上内存释放的代码,而如果需要手动修改,则会报错。如果需要关闭ARC:

选中项目属性—>Build Settings —>搜索“garbage”设置为“NO”即可。

如果需要把你引用的手动的类改为ARC机制:

选中项目属性—>Build Phases —>Compile Sources —>选中你引用的类名在后面添加“-fno-objc-arc”

二、内存管理的原理:引用计数器

解释:当一个对象创建之后它的引用计数为1,当调用这个对象的alloc、retain、new、copy方法之后引用计数器自动在原来的基础上+1(OC中调用一个对象的方法就是给这个对象发送一个消息),当调用这个对象的release方法它的引用计数器-1,如果对象的引用计数器为0,系统自动调用这个对象的dealloc方法来销毁对象。


//重写dealloc方法,在这个方法中通常进行对象释放操作
-(void)dealloc{
[super dealloc];
//注意最后预定要调用父类的dealloc方法(两个目的:1、父类可能有其他引用对象需要释放;2、当前对象的真正释放操作是在super的dealloc中完成的。)
}


Person *p = [[Person alloc]init];
p.name = @"kenshin";
p.age = 22;
NSLog(@"retainCount=%iu",[p retainCount]);
//结果为:1
[p release];
//结果为:InvokePersons's dealloc method.

//上面调用过release方法,p只想的对象就会被销毁,但是此时变量p中还存放着Person对象的地址,
//如果不设置p=nil,则p就是一个野指针,它指向的内存已经不属于这个程序,因此很危险。
p=nil;
//如果不设置p=nil,此时如果再调用对象release会报错,但是如果此时p已经是空指针了。

> OC中给空指针发送任何消息是不会报错的。

//野指针错误形式在Xcode中通常表现为:
//Thread1:EXC_BAD_ACCESS(code=EXC_I386_GPFLT)错误。
因为你访问了一块不属于你的内存。


三、内存管理的原则

遵循法则:谁创建,谁释放。

四、属性参数:



@property的参数分为三类:

默认的参数是:

@property(atomic,readwrite,assign)

1、原子性:一般情况下如果在多线程开发中一个属性可能被两个及两个以上的线程同时访问,此时可以考虑atomaic属性,否则建议使用nonatomic,不加锁,效率较高。
2、读写性:readwrite属相会生成getter、setter两个方法,如果使用readonly则只会生成getter方法。

3、set方法处理:
assign:用于基本数据类型


-(void)setA:(int)a{
_a = a;
}


retain:通常用于非字符串对象


- (void)setA:(Car *)a{
if(_a != a){
[_a release];
_a = [a retain];
}
}


copy:通常用于字符串对象、block、NSArray、NSDictionary


- (void)setA:(NSString *)a{
if(_a != a){
[_a release];
_a = [a copy];
}
}


五、自动释放池

ARC是编译器(时)特性,而不是运行时特性,更不是垃圾回收器(GC)。

不同于XCode4可以在创建工程时选择关闭ARC,XCode5在创建的工程是默认开启ARC,没有可以关闭ARC的选项。

如果需要对特定文件开启或关闭ARC,可以在工程选项中选择Targets -> Compile Phases -> Compile Sources,在里面找到对应文件,添加flag:

打开ARC:-fobjc-arc

关闭ARC:-fno-objc-arc

1、autorelease方法不会改变对象的引用计数器,只是将这个对象放到自动释放池中;

2、自动释放池实质是当自动释放池销毁后调用对象的release方法,不一定就能销毁对象(例如如果一个对象的引用计数器>1则此时就无法销毁);

3、由于自动释放池最后统一销毁对象,因此如果一个操作比较占用内存(对象比较多或者对象占用资源比较多),最好不要放到自动释放池或者考虑放到多个自动释放池;

4、ObjC中类库中的静态方法一般都不需要手动释放,内部已经调用了autorelease方法;

六、ARC的修饰符

ARC主要提供了4种修饰符,他们分别是:__strong,__weak,__autoreleasing,__unsafe_unretained。

__strong

表示引用为强引用。对应在定义property时的”strong”。所有对象只有当没有任何一个强引用指向时,才会被释放。

注意:如果在声明引用时不加修饰符,那么引用将默认是强引用。当需要释放强引用指向的对象时,需要将强引用置nil。

__weak

表示引用为弱引用。对应在定义property时用的”weak”。弱引用不会影响对象的释放,即只要对象没有任何强引用指向,即使有100个弱引用对象指向也没用,该对象依然会被释放。不过好在,对象在被释放的同时,指向它的弱引用会自动被置nil,这个技术叫zeroing weak pointer。这样有效得防止无效指针、野指针的产生。__weak一般用在delegate关系中防止循环引用或者用来修饰指向由Interface Builder编辑与生成的UI控件。

__autoreleasing

表示在autorelease pool中自动释放对象的引用,和MRC时代autorelease的用法相同。定义property时不能使用这个修饰符,任何一个对象的property都不应该是autorelease型的。

一个常见的误解是,在ARC中没有autorelease,因为这样一个“自动释放”看起来好像有点多余。这个误解可能源自于将ARC的“自动”和autorelease“自动”的混淆。其实你只要看一下每个iOS App的main.m文件就能知道,autorelease不仅好好的存在着,并且变得更fashion了:不需要再手工被创建,也不需要再显式得调用[drain]方法释放内存池。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: