iOS開發中的ARC記憶體管理機制(1)——基礎概念
由於移動裝置的記憶體資源一般比較少,所以垃圾回收機制的操作會對裝置的效能造成比較明顯的影響,有可能在執行垃圾回收的時候讓移動裝置出現卡頓,這對於使用者來說是很難受的事。
由此蘋果公司提出了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