@property和@synthesize有以下兩個作用:
1.作用一
@property是在頭檔案.h中聲明一個變量的setter和getter方法。
@synthesize是在.m檔案中定義setter和getter方法的實作。
2.作用二
@property,在聲明變量方法的時候可以附加定義該變量的屬性。如retain,assign,readonly,nonautomic等等。
但是,有一個點需要解釋一下,就是直接使用 變量名指派 和使用 self.變量 指派的差別。比如
.h
ObjctName* nameVarPtr;
@property(nonautomic,retain) ObjctName* nameVarPtr;
.m
self.nameVarPtr = [[ObjectName alloc] init];
int n = [self.nameVarPtr retainCount]; // n = 2
nameVarPtr = [[ObjectName alloc] init];
n = [nameVarPtr retainCount]; // n = 1
self.nameVarPtr = [[ObjectName alloc] init] 和 nameVarPtr = [[ObjectName alloc] init] 兩種指派方式差別何在呢?
self.nameVarPtr=xxx 這種指派方式等價于調用 [self setnameVarPtr:xxx], 而setnameVarPtr:xxx的方法的實作又是依賴于@property的屬性的,比如retain,assign等屬性。
nameVarPtr = xxx 的指派方式,僅僅是對一個指針進行指派。nameVarPtr僅僅是一個指針變量,記錄了xxx的位址。在這個過程中不會調用setter方法,不會調用setter方法,就和@property沒有關系,進而,也和retain,assign等屬性沒有關系。這種指派方式就是一個簡單的指針指派。
綜上,對成員變量進行指派,為防記憶體洩露需要注意的點:
1.self調用setter方法的方式
ObjectName* tmp= [[ObjectName alloc] init];
self.nameVarPtr =tmp; //retainCount=2
[tmp release]; //retainCount=1
2.指針指派方式,不會調用setter方法
nameVarPtr = [[ObjectName alloc] init] ; // retainCount=1
/########################################################################################################################/
@property (nonatomic, assign) NSString *title;
什麼是assign,copy,retain之間的差別?
1,getter=getterName,setter=setterName,設定setter與getter的方法名
2,assign: setter方法直接指派,不進行任何retain操作,不更改索引計數(Reference Counting),為了解決原類型與環循引用問題。
3,retain:setter方法對參數進行release舊值再retain新值,所有實作都是這個順序;釋放舊的對象,将舊對象的值賦予輸入對象,再提高輸入對象的索引計數為1。
4,copy:setter方法進行Copy操作,與retain處理流程一樣,先舊值release,再Copy出新的對象,retainCount為1,這是為了減少對上下文的依賴而引入的機制;建立一個索引計數為1的對象,然後釋放舊對象。
nonatomic:非原子性通路,不加同步,多線程并發通路會提高性能。注意,如果不加此屬性,則預設是兩個通路方法都為原子型事務通路。鎖被加到所屬對象執行個體級。
retain的實際文法為:
- (void)setName:(NSString *)newName {
if (name != newName) {
[name release];
name = [newName retain];
// name’s retain count has been bumped up by 1
}
}
如果你不懂怎麼使用他們,那麼就這樣 ->
使用assign: 對基礎資料類型 (NSInteger,CGFloat)和C資料類型(int, float, double, char, 等等)
使用copy: 對NSString
使用retain: 對其他NSObject和其子類
nonatomic關鍵字:
atomic是Objc使用的一種線程保護技術,基本上來講,是防止在寫未完成的時候被另外一個線程讀取,造成資料錯誤。而這種機制是耗費系統資源的,是以在iPhone這種小型裝置上,如果沒有使用多線程間的通訊程式設計,那麼nonatomic是一個非常好的選擇。
/####################################################################################################################/
使用@property配合@synthesize可以讓編譯器自動實作getter/setter方法,使用的時候也很友善,可以直接使用對象.屬性的方法調用;
如果我們想要對象.方法的方式來調用一個方法并擷取到方法的傳回值,那就需要使用@property配合@dynamic了。
其實使用@dynamic關鍵字是告訴編譯器由我們自己來實作通路方法。如果使用的是@synthesize,那麼這個工作編譯器就會幫你實作了。
readonly
此标記說明屬性是隻讀的,預設的标記是讀寫,如果你指定了隻讀,在@implementation中隻需要一個讀取器。或者如果你使用@synthesize關鍵字,也是有讀取器方法被解析。而且如果你試圖使用點操作符為屬性指派,你将得到一個編譯錯誤。
readwrite
此标記說明屬性會被當成讀寫的,這也是預設屬性。設定器和讀取器都需要在@implementation中實作。如果使用@synthesize關鍵字,讀取器和設定器都會被解析。
assign
對基礎資料類型 (NSInteger,CGFloat)和C資料類型(int, float, double, char, 等等)
此标記說明設定器直接進行指派,這也是預設值。在使用垃圾收集的應用程式中,如果你要一個屬性使用assign,且這個類符合NSCopying協定,你就要明确指出這個标記,而不是簡單地使用預設值,否則的話,你将得到一個編譯警告。這再次向編譯器說明你确實需要指派,即使它是可拷貝的。
retain
對其他NSObject和其子類 對參數進行release舊值,再retain新值
指定retain會在指派時喚醒傳入值的retain消息。此屬性隻能用于Objective-C對象類型,而不能用于Core Foundation對象。(原因很明顯,retain會增加對象的引用計數,而基本資料類型或者Core Foundation對象都沒有引用計數——譯者注)。
copy
對NSString 它指出,在指派時使用傳入值的一份拷貝。拷貝工作由copy方法執行,此屬性隻對那些實行了NSCopying協定的對象類型有效。更深入的讨論,請參考“複制”部分。
注釋:
Copy其實是建立了一個相同的對象,而retain不是:
比如一個NSString 對象,位址為0×1111 ,内容為@”STR”
Copy 到另外一個NSString 之後,位址為0×2222 ,内容相同,新的對象retain為1 ,舊有對象沒有變化
retain 到另外一個NSString 之後,位址相同(建立一個指針,指針拷貝),内容當然相同,這個對象的retain值+1
也就是說,retain 是指針拷貝,copy 是内容拷貝。
nonatomic
禁止多線程,變量保護,提高性能
atomic是Objc使用的一種線程保護技術,基本上來講,是防止在寫未完成的時候被另外一個線程讀取,造成資料錯誤。而這種機制是耗費系統資源的,是以在iPhone這種小型裝置上,如果沒有使用多線程間的通訊程式設計,那麼nonatomic是一個非常好的選擇。
指出通路器不是原子操作,而預設地,通路器是原子操作。這也就是說,在多線程環境下,解析的通路器提供一個對屬性的安全通路,從擷取器得到的傳回值或者通過設定器設定的值可以一次完成,即便是别的線程也正在對其進行通路。如果你不指定 nonatomic ,在自己管理記憶體的環境中,解析的通路器保留并自動釋放傳回的值,如果指定了 nonatomic ,那麼通路器隻是簡單地傳回這個值