@property : iOS6 引入關鍵詞. @property name; 指示編譯器自動生成 name 的 setter 和 getter 方法 : - (NSString *)name; - (NSString *)name { return _name; } - (void)setName ...
@property :
iOS6 引入關鍵詞.
@property name; 指示編譯器自動生成 name 的 setter 和 getter 方法 :
- (NSString *)name;
- (NSString *)name {
return _name;
}
- (void)setName:(NSString *)string;
- (void)setName:(NSString *)string {
if (_name != string) {
[_name release];
_name = [string retain];
}
}
而 @synthesize name = _name; 則是先去訪問同名變數 _name, 沒有則定義變數 _name, 意味著先生成變數, 再生成變數的 setter 及 getter; 如果自己實現了 setter 及 getter 則系統不再實現;
如果使用的是 @synthesize name; 則系統會生成變數 name 而不會生成 _name, getter 及 setter 中所返回也會變為 name.
如果該 property 使用 getter/setter 關鍵字修飾的則會生成對應方法名, 返回值為 @synthesize 後變數名;
如果同時使用 getter 和 setter 關鍵字 且同時手動實現了 setter 和 getter, 則系統不會自動生成變數 _name, 必須使用@synthesize name = xxx 才會生成對應變數;
註 : 預設實現 @synthesize name = _name, _name 可以是任何你想要的變數名.
另 : 對於屬性和變數的理解, 屬性僅僅只表示 setter 和 getter, @property 修飾的屬性僅僅只是 setter 和 getter 縮寫, 方便使用 'self.' 調用, _name 才是真正的變數.
#import "ViewController.h" @interface ViewController () @property (nonatomic, copy) NSString * name; @end @implementation ViewController @synthesize name = userName; - (void)viewDidLoad { [super viewDidLoad]; self.name = @"1111"; NSString * nameString = self.name; NSString * userNameString = userName; NSLog(@"nameString : %@ userNameString : %@", nameString, userNameString); // nameString : 1111 userNameString : 1111 userName = @"2222"; NSLog(@"self.name : %@", self.name); // self.name : 2222 // NSLog(@"%@", _name); // Use of undeclared identifier '_name' } @end
@property 參數:
讀寫 :
readwrite (讀寫) / readonly (只讀),
記憶體管理 :
assign : 預設類型, 對 setter 方法參數不進行 retain 操作, 適用於基本數據類型.
retain : 對 setter 變數舊值進行一次 release 操作, 對參數進行 retain 操作, 適用於對象.
copy : 暫且定義為作用同 retain (具體待深淺拷貝探究).
strong : 同 retain, ARC 下使用.
weak : 作用同 assign, ARC 下使用, 不同的是可以對對象使用, 對象釋放時會將對象置位 nil.
併發性 :
nonatomic / atomic 區別 : 用來決定編譯器在生成的 setter 和 getter 是否為原子操作. atomic 提供線程安全, 描述該變數是否支持多線程同步訪問, 系統會自動創建 lock 鎖鎖定變數, 而 nonatomic 禁止多線程訪問, 保護變數, 提高性能.
屬性預設為 atomic, 為了避免多線程訪問該變數, 造成讀寫的不同步, 編譯器會自動生成一些互斥加鎖代碼, 會損耗性能.
nonatomic : 如果屬性無需考慮多線程的情況, 則可以使用該屬性, 禁止多線程訪問, 提高性能.
atomic : 系統自動生成 setter/getter, 手動生成 setter 和 getter 會警報不能配對.
#import "ViewController.h" @interface ViewController () @property (atomic, copy) NSString * name; @end @implementation ViewController - (void)viewDidLoad { __weak typeof(self) weakself = self; dispatch_async(dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT), ^{ self.name = @"1111"; }); dispatch_async(dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT), ^{ self.name = @"2222"; }); // 兩秒後列印值 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"%@", weakself.name); }); } - (void)setName:(NSString *)name { // Writable atomic property 'name' cannot pair a synthesized getter with a user defined setter _name = name; } @end
nonatomic : 兩個線程訪問 setter, 兩個線程訪問 getter, 如下: 兩次列印結果不定, 可能是 (@"222", @"222") 也可能是 (@"11111", @"11111"), 還可能是 (@"2222", @"11111").
所以說 nonatomic 在多線程情況下會出現問題, 如果是多線程還需進一步處理. ☆☆☆☆☆ -- 怎麼處理???
#import "ViewController.h" @interface ViewController () @property (nonatomic, copy) NSString * name; @end @implementation ViewController - (void)viewDidLoad { __weak typeof(self) weakself = self; dispatch_async(dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT), ^{ weakself.name = @"2222"; }); dispatch_async(dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT), ^{ NSLog(@"%@", weakself.name); }); dispatch_async(dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT), ^{ weakself.name = @"11111"; }); dispatch_async(dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT), ^{ NSLog(@"%@", weakself.name); }); } - (void)setName:(NSString *)name { _name = name; } @end
atomic 示例 :
{lock} if (property != newValue) { [property release]; property = [newValue retain]; } {unlock}
用atomic會在多線程的設值取值時加鎖,中間的執行層是處於被保護的一種狀態,atomic是oc使用的一種線程保護技術,基本上來講,就是防止在寫入未完成的時候被另外一個線程讀取,造成數據錯誤。而這種機制是耗費系統資源的,所以在iPhone這種小型設備上,如果沒有使用多線程間的通訊編程,那麼nonatomic是一個非常好的選擇。
引用參考 : http://www.cnblogs.com/Rong-Shengcom/