iOS开发:ARC下内存回收机制详解,及如何防止内存泄漏
2016-07-26 14:35
507 查看
先看这篇文章,通俗易懂:http://blog.csdn.net/hbw1992322/article/details/52121089
首先,如何打开ARC:
build settings -> searching for ARC -> Objective-C Automatic Reference Counting -> YES
下面我们正式开始认识ARC
有三种指针类型属于ARC管理范畴:
(1)block指针
(2)objective-c对象指针。 如id,class,NSFoo*
(3)标有_attribute_((NSObject))的类型定义(不推荐使用)
其他的指针类型,如int*,CFStringRef(也就是core Foundation类型的,带Ref后缀),不属于ARC管理范畴。
1.1 retain count 语法
指针有可能是空指针或者指向合法对象(valid object)的指针,一个合法的对象必须有reatain,release,autorelease的retain操作。
retain方法:无参,返回一个指向对象的指针
release方法:无参,返回void
autorelease方法:无参,返回一个指向对象的指针
1.2 retained return values
一个方法如果返回一个retainable对象指针,则被定义为返回一个retained value,这代表了调用此方法的caller希望变为此retainable object的第a+1个所有者。 alloc,copy,init,mutableCopy,new方法均会返回一个retainable对象指针,且retain count +1.
1.3 unretained return values
一个方法如果返回一个retainable对象类型,但是不返回一个retained value,那么我们必须确定这个对象在return边界内依然是合法的。
1.4 bridged casts(a C-style cast)
(1) (_bridge T) op; op与T必须一个是retainable object pointer type,另一个是non-retainable pointer type。 这个cast不交换ownership,且ARC不插入retain操作。
(2)(_bridge_reatained T) op; op必须是reatainable object pointer type, T必须是non-retainable pointer type。 ARC会有retain操作。接收者持有retain +1 。
(3)(_bridge_transfer T) op; op必须是non-retainable pointer type, T必须是reatainable object pointer type。 ARC会在封闭的表达范围的最后release the value(ARC will release the value at the end of enclosing full-expression,subject to the usual optimizations on local values)。
(see this gay's conclusion: http://blog.csdn.net/yiyaaixuexi/article/details/8553659)
(1)_autorealeasing
(2)_strong
(3)_unsafe_unretained
(4)_weak
(see this gay's conclusion: http://blog.csdn.net/cuibo1123/article/details/28349793)
当我们创建一个新对象时,他的引用计数为1;
当有一个新的指针指向这个对象时,他的引用计数就加1;
当对象关联的某个指针不再指向他时,他的引用计数就减1;
当对象的引用计数为0时,说明此对象不再被任何指针指向,这时我们就可以将对象销毁,回收内存。
这篇文章非常重要:http://www.cnblogs.com/huangjianwu/p/4962772.html
NSURL *sourceURL; //这个对象为一个全局对象。
{
sourceURL = @"xx/xx/x";
NSArrar *s = [[sourceURL absoluteString]
componentsSeparatedByString:@"/" ];
}
那么在{}结束以后,sourceURL的retainCount会变为3 。
{
sourceURL = @"xx/xx/x";
NSString *str = [sourceURL absoluteString];
NSArrar *s = [
str componentsSeparatedByString:@"/" ];
}
那么在{}结束以后,sourceURL的retainCount会变为2 。
2.第二个坑
(关于free(), malloc()的解释可以参考下面的链接:http://blog.csdn.net/poleness/article/details/27968709)
CFRetain、CFRelease与MRC下的retain、release功能一样, 区别于free(),free会直接将该指针所指向的那块内存释放掉。
3. CF简单的赋值是不会改变引用计数的
assign: 简单赋值,不更改索引计数
copy: 建立一个索引计数为1的对象,然后释放旧对象
retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1
使用含有create或者copy的函数的创建的对象,使用完之后必须释放,否则将导致内存泄漏。
首先,如何打开ARC:
build settings -> searching for ARC -> Objective-C Automatic Reference Counting -> YES
下面我们正式开始认识ARC
1. retainable object pointers
本节介绍retainable object pointers的基本操作,ARC下的运用限制。注意:本节内容是关于指针值(指针所指向的对象的地址),而不是关于指针所指的对象,指针所指的对象的运用规则将会在下一个section介绍。有三种指针类型属于ARC管理范畴:
(1)block指针
(2)objective-c对象指针。 如id,class,NSFoo*
(3)标有_attribute_((NSObject))的类型定义(不推荐使用)
其他的指针类型,如int*,CFStringRef(也就是core Foundation类型的,带Ref后缀),不属于ARC管理范畴。
1.1 retain count 语法
指针有可能是空指针或者指向合法对象(valid object)的指针,一个合法的对象必须有reatain,release,autorelease的retain操作。
retain方法:无参,返回一个指向对象的指针
release方法:无参,返回void
autorelease方法:无参,返回一个指向对象的指针
1.2 retained return values
一个方法如果返回一个retainable对象指针,则被定义为返回一个retained value,这代表了调用此方法的caller希望变为此retainable object的第a+1个所有者。 alloc,copy,init,mutableCopy,new方法均会返回一个retainable对象指针,且retain count +1.
1.3 unretained return values
一个方法如果返回一个retainable对象类型,但是不返回一个retained value,那么我们必须确定这个对象在return边界内依然是合法的。
1.4 bridged casts(a C-style cast)
(1) (_bridge T) op; op与T必须一个是retainable object pointer type,另一个是non-retainable pointer type。 这个cast不交换ownership,且ARC不插入retain操作。
(2)(_bridge_reatained T) op; op必须是reatainable object pointer type, T必须是non-retainable pointer type。 ARC会有retain操作。接收者持有retain +1 。
(3)(_bridge_transfer T) op; op必须是non-retainable pointer type, T必须是reatainable object pointer type。 ARC会在封闭的表达范围的最后release the value(ARC will release the value at the end of enclosing full-expression,subject to the usual optimizations on local values)。
(see this gay's conclusion: http://blog.csdn.net/yiyaaixuexi/article/details/8553659)
2. ownership qualification
有四种ownership qualifiers:(1)_autorealeasing
(2)_strong
(3)_unsafe_unretained
(4)_weak
(see this gay's conclusion: http://blog.csdn.net/cuibo1123/article/details/28349793)
当我们创建一个新对象时,他的引用计数为1;
当有一个新的指针指向这个对象时,他的引用计数就加1;
当对象关联的某个指针不再指向他时,他的引用计数就减1;
当对象的引用计数为0时,说明此对象不再被任何指针指向,这时我们就可以将对象销毁,回收内存。
这篇文章非常重要:http://www.cnblogs.com/huangjianwu/p/4962772.html
接下来自己开始踩坑:
1. 第一个坑: 先来说一件不易被发现的事情NSURL *sourceURL; //这个对象为一个全局对象。
{
sourceURL = @"xx/xx/x";
NSArrar *s = [[sourceURL absoluteString]
componentsSeparatedByString:@"/" ];
}
那么在{}结束以后,sourceURL的retainCount会变为3 。
但是换一种写法:
NSURL *sourceURL; //这个对象为一个全局对象。{
sourceURL = @"xx/xx/x";
NSString *str = [sourceURL absoluteString];
NSArrar *s = [
str componentsSeparatedByString:@"/" ];
}
那么在{}结束以后,sourceURL的retainCount会变为2 。
2.第二个坑
uint32_t* pixels = (uint32_t*)malloc(contextLength); if(pixels == NULL) { NSLog(@"Error: Memory not allocated for bitmap"); CGDataProviderRelease(provider); CGColorSpaceRelease(colorSpace); CGImageRelease(iref); } CGContextRef context = CGBitmapContextCreate(pixels, imageWidth, imageHeight, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo); CFRelease(colorSpace); free(pixels); //请注意这里在创建context之后立刻释放<span style="font-family: Arial, Helvetica, sans-serif;">pixels是可行的,也就是说context会对malloc出来的那块地址多进行一次retain count +1</span> pixels = nil; //所以我们需要对pixels这个指针进行release
(关于free(), malloc()的解释可以参考下面的链接:http://blog.csdn.net/poleness/article/details/27968709)
CFRetain、CFRelease与MRC下的retain、release功能一样, 区别于free(),free会直接将该指针所指向的那块内存释放掉。
3. CF简单的赋值是不会改变引用计数的
assign: 简单赋值,不更改索引计数
copy: 建立一个索引计数为1的对象,然后释放旧对象
retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1
使用含有create或者copy的函数的创建的对象,使用完之后必须释放,否则将导致内存泄漏。
CFDictionaryRef option_dict = (__bridge CFDictionaryRef)options; CFDictionaryRef option_dict2 = option_dict; 这样的cf赋值不会增加option_dict的引用计数
相关文章推荐
- iOS使用Sencha Touch、ExtJs6 Modern或iscroll等框架时,文本框聚焦的光标不跟随页面(文本框)滚动 的解决办法
- iOS 设置view的边框
- Xcode检测解决iOS内存泄露
- iOS开发 ☞ 获取本机ip地址
- iOS开发常用的东西
- IOS邪术之 杀不死的后台&监听进程
- iOS 开发者文档翻译 URL Session的生命周期
- ios-Foundation框架
- iOS图像处理之Core Image ------ 吴白
- 【iOS开发】canOpenURL: failed for URL
- [编写高质量iOS代码的52个有效方法](五)接口与API设计(下)
- Xcode Assets (*.xcassets)
- iOS 开发之多线程的应用场景
- iOS 多线程开发讲解
- iOS基础常用细节问题处理65条
- iOS基础常用细节问题处理65条
- iOS开发-生命周期
- ios9键盘 level级别
- Nagios 使用第三方SMTP发送邮件
- iOS-常见的数据存储方式