屬性宣告語法
@property (attributes) Type name;
屬性屬性分三大類,各自互斥:
1. 記憶體管理語意 (互斥,預設 assign)
| 屬性 | 行為 | Setter 實現邏輯 | 適用場景 |
| assign | 直接指標賦值 | _ivar = newValue; | 基本資料型別 (int, float)、非物件指標、Delegate (避免循環保留) |
| retain | 保留新值、釋放舊值 | if (_ivar != newValue) { [_ivar release]; _ivar = [newValue retain]; } | 物件指標 (ARC 下對應 strong) |
| copy | 複製新值、釋放舊值 | if (_ivar != newValue) { [_ivar release]; _ivar = [newValue copy]; } | 不可變物件對應可變類別 (NSString/NSArray/NSDictionary)、Block |
2. 讀寫權限 (互斥,預設 readwrite)
| 屬性 | 產生方法 | 用途 |
| readwrite | getter + setter | 可讀可寫 |
| readonly | 僅 getter | 不可變屬性、計算屬性 |
readonly 仍可在類別內部透過直接存取 _ivar 或私有分類重寫 setter 修改。
3. 原子性 (互斥,預設 atomic)
| 屬性 | 執行緒安全 | Setter/Getters 實現 | 效能 |
| atomic | 是 (單一存取) | @synchronized(self) { ... } | 較慢 (鎖開銷) |
| nonatomic | 否 | 直接存取 | 快 (預設 iOS 開發推薦) |
注意:atomic 僅保證單一屬性存取原子性,不保證 多屬性邏輯一致性或物件圖完整性。
綜合範例
@interface Person : NSObject
@property (nonatomic, copy) NSString *name; // 複製、非原子、可讀寫
@property (nonatomic, assign) NSInteger age; // 基本型別
@property (nonatomic, weak) id delegate; // 弱引用 (ARC)
@property (readonly) NSString *description; // 唯讀、原子 (預設)
@end
@implementation Person
@synthesize name = _name;
@synthesize age = _age;
@synthesize delegate = _delegate;
// 自訂 setter 示例 (非 ARC 手動管理)
- (void)setName:(NSString *)name {
if (_name != name) {
[_name release];
_name = [name copy]; // copy 語意
}
}
@end
ARC 環境對應關係
| 非 ARC | ARC | 說明 |
| retain | strong | 強引用,增加保留計數 |
| assign | weak / unsafe_unretained | weak 自動置 nil,unsafe_unretained 不置 nil (可能野指標) |
| copy | copy | 同樣複製語意 |
常見陷阱
- mutable 物件用 copy:
@property (copy) NSMutableArray *arr; setter 會呼叫 copy 產生 不可變 NSArray,後續呼叫 addObject: 會崩潰。解決:內部手動 mutableCopy 或宣告為 strong 並文檔說明不可外部修改。
- delegate 循環保留:必須用
weak (ARC) 或 assign (非 ARC)。
- atomic 效能誤區:頻繁存取的屬性 (如遊戲座標) 必須
nonatomic。