strong:使得對(duì)象的引用計(jì)數(shù)器 +1
weak:不會(huì)使得對(duì)象的引用計(jì)數(shù)器 +1
將一個(gè)對(duì)象通過 addXXX 方法添加數(shù)組中時(shí),同樣會(huì)使得對(duì)象的引用計(jì)數(shù)器+1
所以,當(dāng)將一個(gè)實(shí)例添加到self.view中時(shí),引用計(jì)數(shù)器已經(jīng)為1了,視圖是由self.view持有的,如果,一旦添加一個(gè)屬性,聲明一個(gè)單獨(dú)的引用來指向?qū)ο髸r(shí),聲明為strong會(huì)導(dǎo)致計(jì)數(shù)器再+1。當(dāng)視圖需要從self.view中移除掉時(shí),引用計(jì)數(shù)器-1,但計(jì)數(shù)器依然會(huì)因?yàn)檫@個(gè)strong引用的存在而是1,一個(gè)不再出現(xiàn)在界面的視圖,因?yàn)橛?jì)數(shù)器不為0而駐留在內(nèi)容中,是比較浪費(fèi)資源的,所以,添加到self.view中的子視圖,再添加一個(gè)屬性引用時(shí),就不要使用strong,而最好選擇weak。
(weak和strong)不同的是 當(dāng)一個(gè)對(duì)象不再有strong類型的指針指向它的時(shí)候 它會(huì)被釋放? ,即使還有weak型指針指向它。
一旦最后一個(gè)strong型指針離去 ,這個(gè)對(duì)象將被釋放,所有剩余的weak型指針都將被清除。
首先有一點(diǎn),在OC中,如果對(duì)象沒有強(qiáng)引用,就會(huì)被自動(dòng)釋放,那么為什么控件還可以設(shè)為weak?
1. 從storyboard或者xib上創(chuàng)建控件,在控件放在view上的時(shí)候,已經(jīng)形成了如下的引用關(guān)系,以UIButton為例:
UIViewController->UIView->subView->UIButton
然后你為這個(gè)UIButton聲明一個(gè)weak屬性
@property(nonatomic,weak)IBOOutletUIButton*btn;
相當(dāng)于xib/sb對(duì)這個(gè)Button是強(qiáng)引用,你聲明的屬性對(duì)它是弱引用。
2.手動(dòng)創(chuàng)建控件
a). 將控件聲明成strong
@property(nonatomic,strong)UIButton*btn;
那么你在實(shí)現(xiàn)這個(gè)控件時(shí)只需這樣:
_btn = [[UIButton alloc]init];[self.view addSubview:_btn]
b). 將控件聲明成weak
@property(nonatomic,weak) UIButton *btn;
那么你在實(shí)現(xiàn)這個(gè)控件時(shí)需要這樣:
UIButton *button = [[UIButton alloc]init];_btn = button;[self.view addSubview:_btn];
IBOutlet的屬性一般可以設(shè)為weak是因?yàn)樗呀?jīng)被view引用了,除非view被釋放,否則IBOutlet的屬性也不會(huì)被釋放,另外IBOutlet屬性的生命周期和view應(yīng)該是一致的,所以IBOutlet屬性一般設(shè)為weak。
簡(jiǎn)單的說,如果IBOutlet對(duì)象是nib/sb scene的擁有者(File’s owner)所持有的對(duì)象,那么很顯然擁有者必須“擁有”對(duì)象的指針,因此屬性應(yīng)設(shè)置為strong。而其他的IBOutlet對(duì)象的屬性需要設(shè)置為weak,因?yàn)閾碛姓卟⒉恍枰皳碛小彼麄兊闹羔槨Ee例來說,UIViewController的view屬性是strong,因?yàn)閏ontroller要直接擁有view。而添加到view上的subviews,作為IBOutlet只需要設(shè)置為weak就可以了,因?yàn)樗麄儾皇莄ontroller直接擁有的。直接擁有subviews的是controller的view,ARC會(huì)幫助管理內(nèi)存。
第一種情形前面已經(jīng)解釋過了,對(duì)于第二種,通俗點(diǎn)將,就是controller需要直接控制某一個(gè)subview并且將subview添加到其他的view tree上去。
單純從ARC的角度思考,用weak也是很顯然的:因?yàn)閟ubview添加到view上時(shí),view會(huì)“擁有”subview。當(dāng)然,給IBOutlet屬性設(shè)置為strong也沒有錯(cuò),“糾結(jié)誰(shuí)對(duì)誰(shuí)錯(cuò)“的問題可能需要上升到模式或者編碼習(xí)慣的問題,已經(jīng)超出本文的范圍。
assign: 用于非指針變量。用于
基礎(chǔ)數(shù)據(jù)類型 (例如NSInteger)和C數(shù)據(jù)類型(int, float, double, char, 等),另外還有id
如:
@property (nonatomic, assign) int number;
@property (nonatomic, assign) id className;//id必須用assign
反正記住:前面不需要加 “*” 的就用assign吧
retain:用于指針變量。就是說你定義了一個(gè)變量,然后這個(gè)變量在程序的運(yùn)行過程中會(huì)被更改,并且影響到其他方法。一般是用于字符串( NSString,NSMutableString),數(shù)組(NSMutableArray,NSArray),字典對(duì)象,視圖對(duì)象(UIView ),控制器對(duì)象(UIViewController)等 比如:
?@property (nonatomic,retain) NSString * myString;?
@property (nonatomic, retain) UIView * myView;?
@property (nonatomic, retain) UIViewController * myViewController;?
xcode 4.2不支持ARC,所以會(huì)頻繁使用retain來修飾,用完釋放掉,而xcode4.3以后支持ARC,可以使用retian,不需要手動(dòng)釋放內(nèi)存,系統(tǒng)會(huì)自動(dòng)為你完成,如果你在xcode4.3以后上面開發(fā),retian和strong都是一樣的,沒區(qū)別?
strong和weak:
?事實(shí)上 @property(nonatomic,strong) MyClass *myObject;就是相當(dāng)于
@property(nonatomic,retain) MyClass *myObject;
@property(nonatomic, weak )id delegate;就是相當(dāng)于
@property(nonatomic,assign )id delegate;?
?copy:這個(gè)東西估計(jì)是大部分人最不容易搞明白的東西,我也搞不明白。聽別人說這個(gè)東西基本不用了,效果其實(shí)和retain沒什么兩樣,唯一的區(qū)別就是copy只用于NSString而不能用于NSMutableString。 不過好像當(dāng)一個(gè)類繼承NSObject,那么這個(gè)類里面的屬性需要使用copy,比如:?
#import#import@interface Annotation : NSObject{
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
@property (nonatomic) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;
@end
反正以后就這么用就是了
反正就記住一點(diǎn):xcode4.2用retain和assign ;xcode4.3或以上版本用strong與weak 。以前用xcode4.2開發(fā)程序的程序員會(huì)習(xí)慣用retain ,所以代碼都是retian的,新手如果從xcode4.3學(xué)起的話就用strong與weak? 吧,這里面講的區(qū)別有些不對(duì)的地方。
readonly:此標(biāo)記說明屬性是只讀的,默認(rèn)的標(biāo)記是讀寫,如果你指定了只讀,在@implementation中只需要一個(gè)讀取器。或者如果你使用@synthesize關(guān)鍵字,也是有讀取器方法被解析。而且如果你試圖使用點(diǎn)操作符為屬性賦值,你將得到一個(gè)編譯錯(cuò)誤。
readwrite:此標(biāo)記說明屬性會(huì)被當(dāng)成讀寫的,這也是默認(rèn)屬性。設(shè)置器和讀取器都需要在@implementation中實(shí)現(xiàn)。如果使用@synthesize關(guān)鍵字,讀取器和設(shè)置器都會(huì)被解析。
assign:此標(biāo)記說明設(shè)置器直接進(jìn)行賦值,這也是默認(rèn)值。在使用垃圾收集的應(yīng)用程序中,如果你要一個(gè)屬性使用assign,且這個(gè)類符合NSCopying協(xié)議,你就要明確指出這個(gè)標(biāo)記,而不是簡(jiǎn)單地使用默認(rèn)值,否則的話,你將得到一個(gè)編譯警告。這再次向編譯器說明你確實(shí)需要賦值,即使它是可拷貝的。
retain:指定retain會(huì)在賦值時(shí)喚醒傳入值的retain消息。此屬性只能用于Objective-C對(duì)象類型,而不能用于Core Foundation對(duì)象。(原因很明顯,retain會(huì)增加對(duì)象的引用計(jì)數(shù),而基本數(shù)據(jù)類型或者Core Foundation對(duì)象都沒有引用計(jì)數(shù)——譯者注)。
copy:它指出,在賦值時(shí)使用傳入值的一份拷貝。拷貝工作由copy方法執(zhí)行,此屬性只對(duì)那些實(shí)行了NSCopying協(xié)議的對(duì)象類型有效。更深入的討論,請(qǐng)參考“復(fù)制”部分。
nonatomic:指出訪問器不是原子操作,而默認(rèn)地,訪問器是原子操作。這也就是說,在多線程環(huán)境下,解析的訪問器提供一個(gè)對(duì)屬性的安全訪問,從獲取器得到的返回值或者通過設(shè)置器設(shè)置的值可以一次完成,即便是別的線程也正在對(duì)其進(jìn)行訪問。如果你不指定nonatomic,在自己管理內(nèi)存的環(huán)境中,解析的訪問器保留并自動(dòng)釋放返回的值,如果指定了nonatomic,那么訪問器只是簡(jiǎn)單地返回這個(gè)值。
atomic是Objc使用的一種線程保護(hù)技術(shù),基本上來講,是防止在寫未完成的時(shí)候被另外一個(gè)線程讀取,造成數(shù)據(jù)錯(cuò)誤。而這種機(jī)制是耗費(fèi)系統(tǒng)資源的,所以在iPhone這種小型設(shè)備上,如果沒有使用多線程間的通訊編程,那么nonatomic是一個(gè)非常好的選擇。
所以property的屬性默認(rèn)是:readwrite,assign, atomic