由于移动设备的内存资源一般比较少,所以垃圾回收机制的操作会对设备的性能造成比较明显的影响,有可能在执行垃圾回收的时候让移动设备出现卡顿,这对于使用者来说是很难受的事。
由此苹果公司提出了ARC方案。
0x01 自动引用计数
自动引用计数(Automatic Reference Counting,ARC),ARC会追踪程序中的对象并决定哪一个仍会使用到而哪一个不会再用到,在编译期,ARC就已经用更底层的C接口实现了retain/release/autorelease,性能非常好;
不同于垃圾回收器(GC)通过返回的代码来定期检查对象,占用了系统资源。
如果启用了ARC,只管像平常一样按需分配并使用对象,编译器会帮我们插入retain/release语句,相当于编译器替我们完成了内存管理的工作。
0x02 编写ARC代码所需的条件
1、能够确定哪些对象需要进行内存管理
该条件要求对象的最上层集合应该知道如何去管理它的子对象。如果对象是不可保留的,则无法使用ARC特性:
NSString **myString;
myString = malloc(10 * sizeof(NSString *));
//C风格数组是不可保留的对象,不能使用ARC特性
2、能够表明如何去管理对象
该条件要求程序员能够对某个对象的引用计数器值进行+1 / -1操作,NSObject类的子类都能进行内存管理;
3、有可行的办法传递对象的所有权
该条件要求程序能够在调用者和接收者之间传递对象的所有权;
4、编译环境及使用环境:
- Xcode 4.2以上版本;
- Apple LLVM 3.0以上版本的编译器;
- MAC OS X 10.7以上版本的系统;
- 包括归零弱引用(Zeroing Weak Reference),需要iOS 5.0或MAC OS X 10.7以上版本的支持。
0x03 ARC的使用规则
1、代码中不能使用retain、release、retain和autorelease方法;
2、不重载dealloc方法(如果是释放对象内存以外的操作是可以重载该函数的,但是不能直接调用[super dealloc]);
3、不能使用NSAllocateObject和NSDeallocateObject;
4、不能在C结构体中使用对象指针;
5、id与void *间的如果发生所有权传递时需要用特定的方法(__bridge关键字);
6、不能使用NSAutoReleasePool,而需要使用@autoreleasepool块;
7、不能使用“new”开始的属性名称 (如果使用会有下面的编译错误”Property’s synthesized getter follows Cocoa naming convention for returning ‘owned’ objects”);
8、属性不能只有一个read-only而没有内存管理属性,必须指定由谁来管理内存。
0x04 使用ARC的优点
使用ARC后写Objective-C代码就不需要操心复杂的内存管理和担心内存泄露了,把内存管理工作交给编译器,也有利于提高代码效率。最直观的一点就是代码总量变少,更容易阅读:
使用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
使用ARC后:
@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