在 ARC (自動引用計數) 普及前,MRC (手動引用計數) 是 Objective-C 內存管理的基石。理解 MRC 對維護舊代碼、調試 ARC 底層問題、跨語言橋接 (如 Objective-C++) 至關重要。
alloc/new/copy/mutableCopy) 的對象,你擁有 (引用計數 +1),你負責釋放 (release/autorelease)。retain (+1)。retain/alloc/copy 必須配對一個 release/autorelease。dealloc,**切勿直接調用**,重寫 dealloc 釋放持有的資源並調用 [super dealloc]。// Book.h
@interface Book : NSObject
@property (nonatomic, assign) float price; // 基本類型用 assign
- (id)initWithPrice:(float)price;
@end
// Book.m
@implementation Book
@synthesize price = _price;
- (id)initWithPrice:(float)price {
if (self = [super init]) _price = price;
NSLog(@"買入: %.2f", _price);
return self;
}
- (void)dealloc {
NSLog(@"釋放: %.2f", _price);
[super dealloc]; // 必須最後調用
}
@end
// Student.h
@interface Student : NSObject
@property (nonatomic, assign) int age;
@property (nonatomic, retain) Book *book; // 對象屬性用 retain
- (void)setBook:(Book*)book;
- (id)initWithAge:(int)age;
@end
// Student.m
@implementation Student
@synthesize age = _age, book = _book;
- (void)setBook:(Book*)book {
if (_book != book) {
[_book release]; // 釋放舊值
[book retain]; // 保留新值
_book = book;
}
}
- (id)initWithAge:(int)age {
if (self = [super init]) _age = age;
return self;
}
- (void)dealloc {
[_book release]; // 釋放持有對象
[super dealloc];
}
@end
頭文件中僅聲明指針類型屬性/參數時,用 @class Book; 替代 #import "Book.h",減少編譯依賴、避免循環引用。實現文件中再 #import。
@property (nonatomic, retain) Book *book; // nonatomic: 非原子操作,無鎖,性能高 (默認 atomic 加鎖) // retain: setter 釋放舊值、retain 新值 (對象類型) // copy: setter 釋放舊值、copy 新值 (NSString/NSArray/Block 常用) // assign: 直接賦值 (基本類型、非對象指針、weak 代理) @property (nonatomic, assign, getter=isEnabled) BOOL enabled; // 自定義 getter 名
機制:對象發送 autorelease → 加入**當前線程最內層池** → 池排出時發送 release。延遲釋放,適合臨時對象。
// 三種寫法
@autoreleasepool { // 推薦:塊語法,作用域清晰
id obj = [[[MyClass alloc] init] autorelease]; // 1. alloc/init/autorelease 鏈式
id obj2 = [[MyClass alloc] init]; [obj2 autorelease]; // 2. 分步
id obj3 = [MyClass create]; // 3. 類工廠方法內部 autorelease (慣例)
} // 池排出,obj/obj2/obj3 各 release 一次
// 嵌套池:內層池先排出
@autoreleasepool {
@autoreleasepool { /* 內層臨時對象 */ }
/* 外層長期對象 */
}
+ (id)student { // 類方法
return [[[Student alloc] init] autorelease]; // 返回自動釋放對象
}
+ (id)studentWithAge:(int)age {
Student *s = [Student student];
s.age = age;
return s;
}
// 使用:Student *s = [Student studentWithAge:20]; // 無需手動 release
| MRC | ARC | 說明 |
|---|---|---|
retain/release/autorelease | 編譯器自動插入 | 禁止手動調用 |
dealloc 釋放 ivar | 自動釋放 strong ivar | 僅需釋放非對象資源 (文件句柄、C 內存) |
assign (對象) | weak / unsafe_unretained | weak 自動置 nil,安全 |
| @property (retain) | @property (strong) | 語義同義 |
| 循環引用 | 用 weak 打破 | MRC 用 assign 手動管理 |
雖然 ARC 已成主流,但 MRC 思想貫穿 Objective-C 運行時設計,深入掌握能讓你在疑難雜症面前游刃有餘。