atomic:
原子操作(原子性是指事務(wù)的一個(gè)完整操作烛卧,操作成功就提交,反之就回滾. 原子操作就是指具有原子性的操作)在objective-c 屬性設(shè)置里面 默認(rèn)的就是atomic 缝彬,意思就是 setter /getter函數(shù)是一個(gè)原子操作萌焰,如果多線程同時(shí)調(diào)用setter時(shí),不會(huì)出現(xiàn)某一個(gè)線程執(zhí)行完setter所有語(yǔ)句之前谷浅,另一個(gè)線程就開(kāi)始執(zhí)行setter扒俯,相當(dāng)于 函數(shù)頭尾加了鎖 . 這樣的話 并發(fā)訪問(wèn)性能會(huì)比較低 .
nonatomic:
非原子操作 一般不需要多線程支持的時(shí)候就用它,這樣在 并發(fā)訪問(wèn)的時(shí)候效率會(huì)比較高 . 在objective-c里面通常對(duì)象類型都應(yīng)該聲明為非原子性的. iOS中程序啟動(dòng)的時(shí)候系統(tǒng)只會(huì)自動(dòng)生成一個(gè)單一的主線程.程序在執(zhí)行的時(shí)候一般情況下是在同一個(gè)線程里面對(duì)一個(gè)屬性進(jìn)行操作. 如果在程序中 我們確定某一個(gè)屬性會(huì)在多線程中被使用一疯,并且需要做數(shù)據(jù)同步撼玄,就必須設(shè)置成原子性的,但也可以設(shè)置成非原子性的墩邀,然后自己在程序中用加鎖之類的來(lái)做數(shù)據(jù)同步.
在頭文件中聲明屬性的時(shí)候使用atomic 和 nonatomic等價(jià)于在頭文件里面添加2個(gè)函數(shù)一個(gè)是用于設(shè)置這個(gè)屬性的掌猛,一個(gè)是用于讀取這個(gè)屬性,例如:- (nsstring *)name; - (void)setName:(NSString *)str;
atomic / nonatomic 需要和@synthesize/@dynamic配和使用才有意義.
@synthesize
如果沒(méi)有實(shí)現(xiàn)setter和getter方法眉睹,編譯器將會(huì)自動(dòng)在生產(chǎn)setter和getter方法荔茬。
@dynamic
表示變量對(duì)應(yīng)的屬性訪問(wèn)器方法 , 是動(dòng)態(tài)實(shí) 現(xiàn)的 , 你需要在 NSObject 中繼承而來(lái)的 +(BOOL) resolveInstanceMethod:(SEL) sel 方法中指定 動(dòng)態(tài)實(shí)現(xiàn)的方法或者函數(shù)。
屬性修飾其他關(guān)鍵字:
getter=getterName
指定 get 方法辣往,并需要實(shí)現(xiàn)這個(gè)方法 兔院。必須返回與聲明類型相同的變量殖卑,沒(méi)有參數(shù)
setter=setterName
指定 set 方法站削,并需要實(shí)現(xiàn)這個(gè)方法 。帶一個(gè)與聲明類型相同的參數(shù)孵稽,沒(méi)有返回值(返回空值)
當(dāng)聲明為 readonly 的時(shí)候许起,不能指定 set 方法
readwrite
如果沒(méi)有聲明成 readonly ,那就 默認(rèn)是 readwrite 菩鲜≡跋福可以用來(lái)賦值,也可以被賦值
readonly
不可以被賦值
assign
所有屬性都 默認(rèn) assign 接校,通常用于標(biāo)量(簡(jiǎn)單變量 int 猛频, float , CGRect 等)
一種典型情況是用在對(duì)對(duì)象沒(méi)有所有權(quán)的時(shí)候蛛勉,通常是 delegate 鹿寻,避免造成死循環(huán)(如果用 retain 的話會(huì)死循環(huán))
retain
屬性必須是 objc 對(duì)象,擁有對(duì)象所有權(quán)诽凌,必須在 dealloc 中 release 一次毡熏。
copy
屬性必須是 objc 對(duì)象,擁有對(duì)象所有權(quán)侣诵,必須在 dealloc 中 release 一次痢法。且屬性必須實(shí)現(xiàn) NSCopying 協(xié)議
一般常用于 NSString 類型
iOS5以后新加入了ARC狱窘,增加了新的關(guān)鍵字strong, weak, unsafe_unretained
iOS5中新的關(guān)鍵字strong, weak, unsafe_unretained. 可以與以前的關(guān)鍵字對(duì)應(yīng)學(xué)習(xí)strong與retain類似,weak與unsafe_unretained功能差不多(有點(diǎn)區(qū)別财搁,等下會(huì)介紹蘸炸,這兩個(gè)新 關(guān)鍵字與assign類似)。在iOS5中用這些新的關(guān)鍵字尖奔,就可以不用手動(dòng)管理內(nèi)存了幻馁,從java等其它語(yǔ)言轉(zhuǎn)過(guò)來(lái)的程序員非常受用。
strong
strong關(guān)鍵字與retain關(guān)似越锈,用了它仗嗦,引用計(jì)數(shù)自動(dòng)+1,用實(shí)例更能說(shuō)明一切
1 @property (nonatomic, strong) NSString *string1;
2 @property (nonatomic, strong) NSString *string2;
有這樣兩個(gè)屬性
1 @synthesize string1;
2 @synthesize string2;
猜一下下面代碼將輸出什么結(jié)果甘凭?
1 self.string1 = @"String 1";
2 [self.string2 = self.string1;
3 [self.string1 = nil;
4 [NSLog(@"String 2 = %@", self.string2);
結(jié)果是:String 2 = String 1
由于string2是strong定義的屬性稀拐,所以引用計(jì)數(shù)+1,使得它們所指向的值都是@"String 1", 如果你對(duì)retain熟悉的話丹弱,這理解并不難德撬。
weak
接著我們來(lái)看weak關(guān)鍵字:
如果這樣聲明兩個(gè)屬性:
1 @property (nonatomic, strong) NSString *string1;
2 @property (nonatomic, weak) NSString *string2;
并定義
1 @synthesize string1;
2 @synthesize string2;
再來(lái)猜一下,下面輸出是什么躲胳?
1 self.string1 = [[NSString alloc] initWithUTF8String:"string 1"];
2 elf.string2 = self.string1;
3 self.string1 = nil;
4 NSLog(@"String 2 = %@", self.string2);
結(jié)果是:String 2 = null
分析一下蜓洪,由于 self.string1與self.string2指向同一地址,且string2沒(méi)有retain內(nèi)存地址坯苹,而self.string1=nil釋放 了內(nèi)存隆檀,所以string1為nil。聲明為weak的指針粹湃,指針指向的地址一旦被釋放恐仑,這些指針都將被賦值為nil。這樣的好處能有效的防止野指針为鳄。在 c/c++開(kāi)發(fā)過(guò)程中裳仆,為何大牛都說(shuō)指針的空間釋放了后,都要將指針賦為NULL. 在這兒用weak關(guān)鍵字幫我們做了這一步孤钦。
unsafe_unretained
接著我們來(lái)看unsafe_unretained
從名字可以看出歧斟,unretained且unsafe,由于是unretained所以與weak有點(diǎn)類似偏形,但是它是unsafe的静袖,什么是unsafe的呢,下面看實(shí)例壳猜。
如果這樣聲明兩個(gè)屬性:
并定義
1 @property (nonatomic, strong) NSString *string1;
2 @property (nonatomic, unsafe_unretained) NSString *string2;
再來(lái)猜一下勾徽,下面的代碼會(huì)有什么結(jié)果?
1 self.string1 = [[NSString alloc] initWithUTF8String:"string 1"];
2 self.string2 = self.string1;
3 self.string1 = nil;
4 NSLog(@"String 2 = %@", self.string2);
請(qǐng)注意,在此我并沒(méi)有叫你猜會(huì)有什么輸出喘帚,因?yàn)楦静粫?huì)有輸出畅姊,你的程序會(huì)crash掉。 原因是什么吹由,其實(shí) 就是野指針造成的若未,所以野指針是可怕的。為何會(huì)造成野指針呢倾鲫?同于用unsafe_unretained聲明的指針粗合,由于 self.string1=nil已將內(nèi)存釋放掉了,但是string2并不知道已被釋放了乌昔,所以是野指針隙疚。然后訪問(wèn)野指針的內(nèi)存就造成crash. 所以盡量少用unsafe_unretained關(guān)鍵字。