iOS应用开发:什么是ARC?
ARC是什么
ARC是iOS 5推出的新功能,全称叫 ARC(Automatic Reference Counting)。简单地说,就是代码中自动加入了retain/release,原先需要手动添加的用来处理内存管理的引用计数的代码可以自动地由编译器完成了。
该机能在 iOS 5/ Mac OS X 10.7 开始导入,利用 Xcode4.2 可以使用该机能。简单地理解ARC,就是通过指定的语法,让编译器(LLVM 3.0)在编译代码时,自动生成实例的引用计数管理部分代码。有一点,ARC并不是GC,它只是一种代码静态分析(Static Analyzer)工具。
变化点
通过一小段代码,我们看看使用ARC前后的变化点。
- @interface NonARCObject : NSObject {
- NSString *name;
- }
- -(id)initWithName:(NSString *)name;
- @end
- @implementation NonARCObject
- -(id)initWithName:(NSString *)newName {
- self = [super init];
- if (self) {
- name = [newName retain];
- }
- return self;
- }
- -(void)dealloc {
- [name release];
- [Super dealloc];
- }
- @end
- @interface ARCObject : NSObject {
- NSString *name;
- }
- -(id)initWithName:(NSString *)name;
- @end
- @implementation ARCObject
- -(id)initWithName:(NSString *)newName {
- self = [super init];
- if (self) {
- name = newName;
- }
- return self;
- }
- @end
- 生成对象时,使用autorelease
- 对象代入时,先autorelease后再retain
- 对象在函数中返回时,使用return [[object retain] autorelease];
而使用ARC后,我们可以不需要这样做了,甚至连最基础的release都不需要了。
使用ARC的好处
使用ARC有什么好处呢?
- 看到上面的例子,大家就知道了,以后写Objective-C的代码变得简单多了,因为我们不需要担心烦人的内存管理,担心内存泄露了
- 代码的总量变少了,看上去清爽了不少,也节省了劳动力
- 代码高速化,由于使用编译器管理引用计数,减少了低效代码的可能性
不好的地方
- 记住一堆新的ARC规则 — 关键字及特性等需要一定的学习周期
- 一些旧的代码,第三方代码使用的时候比较麻烦;修改代码需要工数,要么修改编译开关
关于第二点,由于 XCode4.2 中缺省ARC就是 ON 的状态,所以编译旧代码的时候往往有"Automatic Reference Counting Issue"的错误信息。

这个时候,可以将项目编译设置中的“Objectice-C Auto Reference Counteting”设为NO。如下所示。

如果只想对某个.m文件不适应ARC,可以只针对该类文件加上 -fno-objc-arc 编译FLAGS,如下图。

ARC基本规则
- retain, release, autorelease, dealloc由编译器自动插入,不能在代码中调用
- dealloc虽然可以被重载,但是不能调用[super dealloc]
由于ARC并不是GC,并需要一些规则让编译器支持代码插入,所以必须清楚清楚了这些规则后,才能写出健壮的代码。
Objective-C对象
ObjectiveC中的对象,有强参照(Strong reference)和弱参照(Weak reference)之分,当需要保持其他对象的时候,需要retain以确保对象引用计数加1。对象的持有者(owner)只要存在,那么该对象的强参照就一直存在。
对象处理的基本规则是
- 只要对象的持有者存在(对象被强参照),那么就可以使用该对象
- 对象失去了持有者后,即被破弃
强参照 (Strong reference)
(s1)
firstName作为”natsu”字符串对象的最初持有者,是该NSString类型对象的Strong reference。
(s2)
这里将firstName代入到aName中,即aName也成为了@”natsu”字符串对象的持有者,对于该对象,aName也是Strong reference。
(s3)
这里,改变firstName的内容。生成新的字符串对象”maki”。这时候firstName成为”maki”的持有者,而@”natsu”的持有者只有aName。每个字符串对象都有各自的持有者,所以它们都在内存中都存在。
(s4)
追加新的变量otherName, 它将成为@”maki”对象的另一个持有者。即NSString类型对象的Strong reference。
(s5)
将otherName代入到aName,这时,aName将成为@”maki”字符串对象的持有者。而对象@”natsu”已经没有持有者了,该对象将被破弃。
弱参照 (Weak reference)
接下来我们来看看弱参照 (Weak reference) 的使用方式。

(w1)
与强参照方式同样,firstName作为字符串对象@”natsu”的持有者存在。即是该NSString类型对象的Strong reference。
(w2)
使用关键字__weak,声明弱参照weakName变量,将firstName代入。这时weakName虽然参照@”natsu”,但仍是Weak reference。即weakName虽然能看到@”natsu”,但不是其持有者。
(w3)
firstName指向了新的对象@”maki”,成为其持有者,而对象@”natsu”因为没有了持有者,即被破弃。同时weakName变量将被自动代入nil。
引用关键字
ARC中关于对象的引用参照,主要有下面几关键字。使用strong, weak, autoreleasing限定的变量会被隐式初始化为nil。
- __strong
变量声明缺省都带有__strong关键字,如果变量什么关键字都不写,那么缺省就是强参照。
- __weak
上面已经看到了,这是弱参照的关键字。该概念是新特性,从 iOS 5/ Mac OS X 10.7 开始导入。由于该类型不影响对象的生命周期,所以如果对象之前就没有持有者,那么会出现刚创建就被破弃的问题,比如下面的代码。
- NSString __weak *string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]];
- NSLog(@"string: %@", string); //此时 string为空
如果编译设定OS版本 Deployment Target 设定为这比这低的版本,那么编译时将报错(The current deployment target does not support automated __weak references),这个时候,我们可以使用下面的 __unsafe_unretained。
弱参照还有一个特征,即当参数对象失去所有者之后,变量会被自动付上nil (Zeroing)。
- __unsafe_unretained
该关键字与__weak一样,也是弱参照,与__weak的区别只是是否执行nil赋值(Zeroing)。但是这样,需要注意变量所指的对象已经被破弃了,地址还还存在,但内存中对象已经没有了。如果还是访问该对象,将引起「BAD_ACCESS」错误。
- __autoreleasing
该关键字使对像延迟释放。比如你想传一个未初始化的对像引用到一个方法当中,在此方法中实例化此对像,那么这种情况可以使用__autoreleasing。他被经常用于函数有值参数返回时的处理,比如下面的例子。
- - (void) generateErrorInVariable:(__autoreleasing NSError **)paramError {
- ....
- *paramError = [[NSError alloc] initWithDomain:@"MyApp" code:1 userInfo:errorDictionary];
- }
- ....
- {
- NSError *error = nil;
- [self generateErrorInVariable:&error];
- NSLog(@"Error = %@", error);
- }
又如函数的返回值是在函数中申请的,那么希望释放是在调用端时,往往有下面的代码。
- -(NSString *)stringTest
- {
- NSString *retStr = [NSString stringWithString:@"test"];
- return [[retStr retain] autorelease];
- }
- // 使用ARC
- -(NSString *)stringTest
- {
- __autoreleasing NSString *retStr = [NSString alloc] initWithString:@"test"];
- return retStr;
- }
即当方法的参数是id*,且希望方法返回时对象被autoreleased,那么使用该关键字。
总结
今天,我们看到了基本的ARC使用规则
- 代码中不能使用retain, release, retain, autorelease
- 不重载dealloc(如果是释放对象内存以外的处理,是可以重载该函数的,但是不能调用[super dealloc])
- 不能使用NSAllocateObject, NSDeallocateObject
- 不能在C结构体中使用对象指针
- id与void *间的如果cast时需要用特定的方法(__bridge关键字)
- 不能使用NSAutoReleasePool、而需要@autoreleasepool块
- 不能使用“new”开始的属性名称 (如果使用会有下面的编译错误”Property’s synthesized getter follows Cocoa naming convention for returning ‘owned’ objects”)
iOS应用开发:什么是ARC?的更多相关文章
- 手把手教你ARC——iOS/Mac开发ARC入门和使用
转载自:http://www.onevcat.com/2012/06/arc-hand-by-hand/ 本文部分实例取自iOS 5 Toturail一书中关于ARC的教程和公开内容,仅用于技术交流和 ...
- iOS 非ARC基本内存管理系列 -手把手教你ARC——iOS/Mac开发ARC入门和使用(转)
手把手教你ARC——iOS/Mac开发ARC入门和使用 Revolution of Objective-c 本文部分实例取自iOS 5 Toturail一书中关于ARC的教程和公开内容,仅用于技术交流 ...
- iOS多线程开发
概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操 ...
- iOS移动开发周报-第25期
iOS移动开发周报-第25期 [摘要]:本期iOS移动开发周报带来如下内容:苹果发布 iPhone6 和 Apple Watch.Swift 1.0 GM发布.Xcode 6支持PDF Vector作 ...
- iOS应用开发详解
<iOS应用开发详解> 基本信息 作者: 郭宏志 出版社:电子工业出版社 ISBN:9787121207075 上架时间:2013-6-28 出版日期:2013 年7月 开本:16开 ...
- 中文 iOS/Mac 开发博客列表
中文 iOS/Mac 开发博客列表 博客地址 RSS地址 OneV's Den http://onevcat.com/atom.xml 一只魔法师的工坊 http://blog.ibireme.com ...
- Unity iOS混合开发界面切换思路
Unity iOS混合开发界面切换思路 最近有很多博友QQ 私信 或则 留言联系我,请教iOS和Unity界面之前相互切换的问题,源代码就不私下发你们了,界面跳转功能的代码我直接贴到下面好了,顺带说i ...
- ios新手开发——toast提示和旋转图片加载框
不知不觉自学ios已经四个月了,从OC语法到app开发,过程虽然枯燥无味,但是结果还是挺有成就感的,在此分享我的ios开发之路中的小小心得~废话不多说,先上我们今天要实现的效果图: 有过一点做APP经 ...
- iOS常用开发技巧
iOS开发过程中,总有那么一些个小问题让人纠结,它们不会让程序崩溃,但是会让人崩溃.除此之外,还将分享一些细节现在我通过自己的总结以及从其他地方的引用,来总结一下一些常见小问题. 本篇长期更新,多积累 ...
随机推荐
- tomcat 配置https (单向认证)
1.单向认证,就是传输的数据加密过了,但是不会校验客户端的来源 2.双向认证,如果客户端浏览器没有导入客户端证书,是访问不了web系统的,找不到地址 如果只是加密,单向就行 如果想要用系统的人没有证书 ...
- java base64编码 加密和解密(切记注意乱码问题)
BASE64 编码是一种常用的字符编码,在很多地方都会用到.JDK 中提供了非常方便的 BASE64Encoder 和 BASE64Decoder,用它们可以非常方便的完成基于 BASE64 的编码和 ...
- 【设计模式 - 14】之命令模式(Command)
1 模式简介 命令模式的定义: 命令模式将命令封装成对象,从而使调用一个命令变为调用一个对象的指定方法. 命令模式的优点: 1) 降低了系统耦合度: 2) 新的命 ...
- Android中的主题Theme
系统自带的Theme: android以及为我们定义好了一些theme,需要是我们直接可以拿来使用. 常用的Theme通常如下: android:theme="@android:style ...
- 在LaTeX里插入全页的pdf 分类: LaTex 2015-02-04 17:20 142人阅读 评论(0) 收藏
要帮女友排版毕业论文,需要插入封面,省时省力的方法就是把学校给的Word封面保存成PDF然后插入到Latex文档中. 首先添加下面的宏: \usepackage[final]{pdfpages} 然后 ...
- 将html中的br换行符转换为文本输入中的换行符(转)
PHP中的有个非常好的函数:nl2br(),将文本框中的换行转换为HTML页面的<br />,但是如何实现将html中的<br />换行符转换为文本框中的换行符呢?下面这几个方 ...
- android开发之broadcast学习笔记 分类: android 学习笔记 2015-07-19 16:33 32人阅读 评论(0) 收藏
android中的广播用的太多了,今天稍微总结一下. 按注册方式分为两种: 1.静态注册广播: 静态注册广播就是在androidManifest.xml文件中注册广播,假设我们要实现这样一个效果,在一 ...
- GUI编程笔记(java)11:使用Netbeans工具进行GUI编程
Netbeans工具:是基于java语言进行GUI界面设计的工具 Visual Studio工具:是基于C#语言进行GUI界面设计的工具
- jQuery Capty 图片标题插件
jQuery Capty是可以为图片添加漂亮的字幕的插件 文件包含: <link type="text/css" rel="stylesheet" hre ...
- Session 原理
Session天天用,但是你真的理解了么? 今天遇到了这个问题,于是研究了一下.要解决这个问题,首先就要明白一些Session的机理.Session在服务器是以散列表形式存在的,我们都知道Sessio ...