由于移動裝置的記憶體資源一般比較少,是以垃圾回收機制的操作會對裝置的性能造成比較明顯的影響,有可能在執行垃圾回收的時候讓移動裝置出現卡頓,這對于使用者來說是很難受的事。
由此蘋果公司提出了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