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
我们之前使用Objective-C中内存管理规则时,往往采用下面的准则
  • 生成对象时,使用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: 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”)

ARC的更多相关文章

  1. Convert BSpline Curve to Arc Spline in OpenCASCADE

    Convert BSpline Curve to Arc Spline in OpenCASCADE eryar@163.com Abstract. The paper based on OpenCA ...

  2. 黑马程序员——ARC机制总结和用ARC建立模型

    ARC 全称:Automatic Reference Counting 使用ARC 只需要在建立一个新的项目的时候把 下面的√打上 Xcode5以后都会默认建议开发者使用ARC机制 新的项目中如果有部 ...

  3. JSONKit在项目中使用设置(ARC与方法更新)

    在项目中经常会遇到解析json的情况,如果有同学想要解析JSON,那么JSONKit可以是一个不错的选择. git中JSONKit 的地址为:https://github.com/johnezang/ ...

  4. MRC迁移ARC之__block

    今日帮着同事把老项目从MRC迁移至ARC,大部分工作无非是删除release,[super dealloc]等方法,只要关闭了MRC编译选项后,编译器能自动帮你检查,block就有一些不一样了,发现许 ...

  5. Arc GIS engine10.2与VS2012的安装及匹配步骤

      本文章已收录于:   .embody { padding: 10px 10px 10px; margin: 0 -20px; border-bottom: solid 1px #ededed } ...

  6. 关于ARC下需要dealloc的相关内容

    今天在项目中使用KVO添加观察者模式的时候,在返回上一级的时候竟然崩了.可是,看了很久,代码没有问题.最后,终于知道了需要添加dealloc 防止以后再出错,所以,便纪录下来.关于ARC下需要手动释放 ...

  7. iOS 中 ARC 项目 兼容 MRC

    iOS 项目中MRC 和 ARC 项目的代码兼容问题: 1.ARC 项目中导入 MRC 第三方类的时候要在此类上添加 -objc-arc. 2.MRC 项目中导入 ARC 类的时候要在次类上添加 -f ...

  8. ARC内存管理机制详解

    ARC在OC里面个人感觉又是一个高大上的牛词,在前面Objective-C中的内存管理部分提到了ARC内存管理机制,ARC是Automatic Reference Counting---自动引用计数. ...

  9. objective-c 语法快速过(7)编译器特性ARC

    ARC(是编译器特性) ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内 ...

  10. iOS通过ARC管理内存(内容根据iOS编程编写)

    栈 当程序执行某个方法(或函数)时,会从内存中一个叫栈的区域分配一块内存空间,这块内存空间我们叫帧.帧负责保护程序在方法内声明的变量的值.在方法内声明的变量我们称之为局部变量. 当我们的程序开始启动, ...

随机推荐

  1. Python标准模块--collections

    1.模块简介 collections包含了一些特殊的容器,针对Python内置的容器,例如list.dict.set和tuple,提供了另一种选择: namedtuple,可以创建包含名称的tuple ...

  2. 可惜Java中没有yield return

    项目中一个消息推送需求,推送的用户数几百万,用户清单很简单就是一个txt文件,是由hadoop计算出来的.格式大概如下: uid caller 123456 12345678901 789101 12 ...

  3. ASP.NET Web API 异常日志记录

    如果在 ASP.NET MVC 应用程序中记录异常信息,我们只需要在 Global.asax 的 Application_Error 中添加代码就可以了,比如: public class MvcApp ...

  4. 【记录】VS2012新建MVC3/MVC4项目时,报:此模板尝试加载组件程序集“NuGet.VisualStudio.Interop...”

    最近电脑装了 VisualStudio "14" CTP,由于把其他版本的 VS 卸掉,由高到低版本安装,当时安装完 VisualStudio "14" CTP ...

  5. 改变word的语言字典

    改变word的语言字典 上周末看论坛有人提出否有方法用代码改变word的语言字典,因为默认的语言会影响现用语言输入的拼写器和其他校对工具.我们的Spire.doc正好支持,正好闲来无事所以我用西班牙语 ...

  6. Android动画的理解

    基础知识 在我们开始讲Android动画这个知识点之前,我们了解下相应的基础知识点. Shape篇 一般用Shape定义的XML文件是存放在Drawable目录下,广泛应用于在Button.TextV ...

  7. 记录下Sublime Text Mac版的快捷键【转】

    推荐使用最新版本的Chrome/Safari或者Firefox浏览器浏览此页,否则Mac按键可能无法正常展示 The Latest Version of Chrome/Safari or Firefo ...

  8. PHP配置限制文件大小上传

    修改PHP上传文件大小限制的方法1. 一般的文件上传,除非文件很小.就像一个5M的文件,很可能要超过一分钟才能上传完.但在php中,默认的该页最久执行时间为 30 秒.就是说超过30秒,该脚本就停止执 ...

  9. 【十大经典数据挖掘算法】kNN

    [十大经典数据挖掘算法]系列 C4.5 K-Means SVM Apriori EM PageRank AdaBoost kNN Naïve Bayes CART 1. 引言 顶级数据挖掘会议ICDM ...

  10. 从 AJAX 到 JSONP的基础学习

    目录索引: 一.AJAX的概念二.POST && GET三.原生实现AJAX简单示例 3.1 实现代码 3.2 重点说明四.框架隐藏域 4.1 基本概念 4.2 后台写入脚本 4.3 ...