开始使用ARC
Automatic Reference Counting (ARC)是编译器自动管理Objective-C对象的一个功能,相对于不得不考虑retain和release操作来说,ARC让我们有更多的精力集中在我们应用内有趣的代码、object graphs和对象之间的关系上。
概要
ARC是用过来在编译的时候添加适当的代码来保证对象在有用的时候有效,没有了就不再有效了。从概念上讲,ARC通过调用合适的内存管理方法遵循着和 manual reference counting(MRC)同样的内存管理规则。
为了让编译器产生正确的代码,ARC严格规定了你可以调用的方法和怎样使用toll-free bridging。ARC引入了新的用于对象引用和属性声明的生命周期标识符。
ARC支持Xcode 4.2 for OS X v10.6 and v10.7 (64-bit applications) and for iOS 4 and iOS 5。弱引用不支持OS X v10.6 and iOS 4。
Xcode提供了一个工具用来把非ARC代码自动转换到ARC代码(例如移除retain和release的调用),解决的不能自动迁移的问题。这个工具会把工程中的所有文件都转换成ARC,在使用非ARC方便的情况下,你也可以选择某些文件使用ARC。
ARC概况
不用再记住什么时候该使用retain、release和autorelease了,ARC知道你的对象的使用周期然后在编译的时候加入了合适的内存管理代码。编译器也会为你生成合适的dealloc方法。如果你刚刚使用ARC,那么传统的Cocoa的命名规范在你管理MRC的代码的时候是非常重要的。
一个完整的正确的Person类的实现是这样的:
- @interface Person : NSObject
- @property NSString *firstName;
- @property NSString *lastName;
- @property NSNumber *yearOfBirth;
- @property Person *spouse;
- @end
- @implementation Person
- @end
对象的属性默认是strong的。
使用ARC,你可能实现这样一个方法contrived :
- - (void)contrived {
- Person *aPerson = [[Person alloc] init];
- [aPerson setFirstName:@"William"];
- [aPerson setLastName:@"Dudney"];
- [aPerson setYearOfBirth:[[NSNumber alloc] initWithInteger:2011]];
- NSLog(@"aPerson: %@", aPerson);
- }
ARC接管里内存管理,所以Person和NSNumber都不会造成内存泄露。
你也可以安全的实现一个Person的方法takeLastNameFrom:
- - (void)takeLastNameFrom:(Person *)person {
- NSString *oldLastname = [self lastName];
- [self setLastName:[person lastName]];
- NSLog(@"Lastname changed from %@ to %@", oldLastname, [self lastName]);
- }
ARC能够确保 oldLastName
在NSLog之前不被释放。
ARC强制的新规则
ARC提出了一些新的别的编译器没有的新规则。这些规定是为了能够提供一个完整的可靠的内存管理模型。在一些情况能够很简单的提升性能,在一些情况下能够简化代码或者让你不用处理内存管理。如果你违背这些规则,在编译的时候就会出错,而不是在运行的时候产生错误。
- 你不能显示的调用dealloc,实现或者调用retain、release、retianCount或者autorealease。
@selector(retain)
, @selector(release)等等
- 你不能使用
NSAllocateObject 和
NSDeallocateObject
- 在C结构体中不能使用对象指针。
- 不能随便的转换id和void*
- 你不能是用NSAutoreleasePool
- 你不能是用内存zones
- 不能提供以new开头的获取方法,这意味着你不能添加一个以new开头的属性,而不自己添加get方法。
- // Won't work:
- @property NSString *newTitle;
- // Works:
- @property (getter=theNewTitle) NSString *newTitle;
ARC提出了新的生命周期标识符
Property属性
- // The following declaration is a synonym for: @property(retain) MyClass *myObject;
- @property(strong) MyClass *myObject;
- // The following declaration is similar to "@property(assign) MyClass *myObject;"
- // except that if the MyClass instance is deallocated,
- // the property value is set to nil instead of remaining as a dangling pointer.
- @property(weak) MyClass *myObject;
在ARC下,strong是默认的对象类型。
变量标识符
- __strong
- __weak
- __unsafe_unretained
- __autoreleasing
- __strong是默认的,一个对象只要有__strong类型指针指向它,它就有效。
- __weak声明了一个引用并不持有该对象。当没有强引用指向弱引用指向的对象的时候,弱引用被赋值为nil。
- __unsafe__unretain声明了一个不持有对象的引用。当没有强引用指向该对象的时候,该引用不会被赋值为nil,所以当一个该引用指向的对象被回收的时候,该引用是危险的。
- __autorelease是用来声明通过id*传递并返回autorelease的参数的。
- ClassName * qualifier variableName;
例如:
- MyClass * __weak myWeakReference;
- MyClass * __unsafe_unretained myUnsafeReference;
其他变种写法在技术上是不正确的,当时是被编译器允许,想要了解更过可以看这里: http://cdecl.org/
- NSString * __weak string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]];
- NSLog(@"string: %@", string);
虽然string是在初始化赋值之后使用的,但是在赋值的时候没有强引用指向string,因此它立刻就会被释放。NSLog语句会输出一个null值(在此例子中编译器会给出警告)。
- NSError *error;
- BOOL OK = [myObject performOperationWithError:&error];
- if (!OK) {
- // Report the error.
- // ...
然而这个声明是错误的而且是隐式的。
- NSError * __strong e;
其实这个方法的声明如下:
- -(BOOL)performOperationWithError:(NSError * __autoreleasing *)error;
- NSError * __strong error;
- NSError * __autoreleasing tmp = error;
- BOOL OK = [myObject performOperationWithError:&tmp];
- error = tmp;
- if (!OK) {
- // Report the error.
- // ...
使用生命周期标识符避免循环引用
- MyViewController *myController = [[MyViewController alloc] init…];
- // ...
- myController.completionHandler = ^(NSInteger result) {
- [myController dismissViewControllerAnimated:YES completion:nil];
- };
- [self presentViewController:myController animated:YES completion:^{
- [myController release];
- }];
正像是描述的一样,你可以使用__block标识符,在completion handler内设置myController为nil:
- MyViewController * __block myController = [[MyViewController alloc] init…];
- // ...
- myController.completionHandler = ^(NSInteger result) {
- [myController dismissViewControllerAnimated:YES completion:nil];
- myController = nil;
- };
另外,你可以使用一个临时的__weak变量。下面的例子声明了一个简单是实现:
- MyViewController *myController = [[MyViewController alloc] init…];
- // ...
- MyViewController * __weak weakMyViewController = myController;
- myController.completionHandler = ^(NSInteger result) {
- [weakMyViewController dismissViewControllerAnimated:YES completion:nil];
- };
没有了循环引用,但是你应该这样用:
- MyViewController *myController = [[MyViewController alloc] init…];
- // ...
- MyViewController * __weak weakMyController = myController;
- myController.completionHandler = ^(NSInteger result) {
- MyViewController *strongMyController = weakMyController;
- if (strongMyController) {
- // ...
- [strongMyController dismissViewControllerAnimated:YES completion:nil];
- // ...
- }
- else {
- // Probably nothing...
- }
- };
在一些情况下如果__weak是不兼容的你可能使用__unsafe__unretained。然而对于循环引用这个可能变得不切实际,因为是非常难得或者不可能验证__unsafe__unretained指针是有效的和指向了同样有问题的对象。
ARC使用了新的语句来管理Autorelease Pools
- @autoreleasepool {
- // Code, such as a loop that creates a large number of temporary objects.
- }
这个简单的结构可以允许编译器来推断引用计数状态。在入口处,一个autorelease pool被放进栈。在退出的地方(break,return,goto,fall-through等等)autorelease pool被弹出栈。为了兼容已经存在的代码,如果由于异常退出,autorelease pool是不会被弹出栈的。
Patterns for Managing Outlets Become Consistent Across Platforms(管理Outlets)
栈变量初始化为nil
- - (void)myMethod {
- NSString *name;
- NSLog(@"name: %@", name);
- }
NSLog语句将会输出null而不是crashing。
使用编译标志来开启和关闭ARC
管理Toll-Free-Bridging
开始使用ARC的更多相关文章
- 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 ...
- 黑马程序员——ARC机制总结和用ARC建立模型
ARC 全称:Automatic Reference Counting 使用ARC 只需要在建立一个新的项目的时候把 下面的√打上 Xcode5以后都会默认建议开发者使用ARC机制 新的项目中如果有部 ...
- JSONKit在项目中使用设置(ARC与方法更新)
在项目中经常会遇到解析json的情况,如果有同学想要解析JSON,那么JSONKit可以是一个不错的选择. git中JSONKit 的地址为:https://github.com/johnezang/ ...
- MRC迁移ARC之__block
今日帮着同事把老项目从MRC迁移至ARC,大部分工作无非是删除release,[super dealloc]等方法,只要关闭了MRC编译选项后,编译器能自动帮你检查,block就有一些不一样了,发现许 ...
- Arc GIS engine10.2与VS2012的安装及匹配步骤
本文章已收录于: .embody { padding: 10px 10px 10px; margin: 0 -20px; border-bottom: solid 1px #ededed } ...
- 关于ARC下需要dealloc的相关内容
今天在项目中使用KVO添加观察者模式的时候,在返回上一级的时候竟然崩了.可是,看了很久,代码没有问题.最后,终于知道了需要添加dealloc 防止以后再出错,所以,便纪录下来.关于ARC下需要手动释放 ...
- iOS 中 ARC 项目 兼容 MRC
iOS 项目中MRC 和 ARC 项目的代码兼容问题: 1.ARC 项目中导入 MRC 第三方类的时候要在此类上添加 -objc-arc. 2.MRC 项目中导入 ARC 类的时候要在次类上添加 -f ...
- ARC内存管理机制详解
ARC在OC里面个人感觉又是一个高大上的牛词,在前面Objective-C中的内存管理部分提到了ARC内存管理机制,ARC是Automatic Reference Counting---自动引用计数. ...
- objective-c 语法快速过(7)编译器特性ARC
ARC(是编译器特性) ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内 ...
- iOS通过ARC管理内存(内容根据iOS编程编写)
栈 当程序执行某个方法(或函数)时,会从内存中一个叫栈的区域分配一块内存空间,这块内存空间我们叫帧.帧负责保护程序在方法内声明的变量的值.在方法内声明的变量我们称之为局部变量. 当我们的程序开始启动, ...
随机推荐
- C#提高-------------------Module的使用
如果没有看<C#反射(一)>.建议先看<C#反射(一)>再看这一篇.上一篇文章发表,有人评论我所写的东西比较基础.其实我也知道我也只不过是在写最基础的语法而已,之所以写它是因为 ...
- C# 批量生成邮箱地址代码
如图,是我生成好的5万条邮箱数据, 其实,网上有大量批量生成邮箱的软件,多种多样的生成格式,各种设置,各种组合, 我不需要那么强大,只需要生成不重复的邮箱地址即可,所以,我懒得从网上下载了, 反正就几 ...
- Java设计模式之十一种行为型模式(附实例和详解)
Java经典设计模式共有21中,分为三大类:创建型模式(5种).结构型模式(7种)和行为型模式(11种). 本文主要讲行为型模式,创建型模式和结构型模式可以看博主的另外两篇文章:J设计模式之五大创建型 ...
- linux下配置SS5(SOCK5)代理服务
安装sock5所需依赖开发库: # yum install pam-devel openldap-devel openssl-devel 下载并解压安装sock5 # wget http://down ...
- RGB转LAB色彩空间
1.原理 RGB无法直接转换成LAB,需要先转换成XYZ再转换成LAB,即:RGB——XYZ——LAB 因此转换公式分两部分: (1)RGB转XYZ 假设r,g,b为像素三个通道,取值范围均为[0,2 ...
- lnmp手动新建虚拟机
1.在home/wwwroot/zhongjie 新建zhongjie文件夹 2.在usr/local/nginx/conf/vhost/zhongjie.conf 新建配置文件zhongj ...
- Android开发学习笔记-GridView的动态显示
1.添加GridItem布局文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout x ...
- ActiveMQ的消息存储方式
1. 队列存储 采取先进先出模式,同一时间,消息只会发送给某一个消费者,只有当该消息被消费并告知已收到时,它才能在代理的存储中被删除. 对于持久性订阅来说,每一个消费者都会 ...
- 完美解决ListView中事件ItemCreated中使用ClientID导致插入数据失败
于昨天晚上看到视频做到这个例子,但是发现始终有错误,在ListView的ItemCreated事件中使用了ClientID则会导致数据插入数据库失败.当点击插入按钮时,网页就像点击F5刷新一样,无任何 ...
- 关于测试中哪些信息需要放到jira上面
1.每个新需求的功能点,全部在jira上一一呈现 2.每个bug也一样在jira上一一呈现 3.任务一个需要优化改进的点也一一在jira上呈现 然后程序员一直开发新功能和修改新bug,测试人员负责bu ...