@property與@synthesize是成對出現(xiàn)的,可以自動生成某個類成員變量的存取方法爱谁。在Xcode4.5以及以后的版本,@synthesize可以省略。
1.atomic與nonatomic
atomic:默認是有該屬性的锯七,這個屬性是為了保證程序在多線程情況,編譯器會自動生成一些互斥加鎖代碼誉己,避免該變量的讀寫不同步問題眉尸。
nonatomic:如果該對象無需考慮多線程的情況,請加入這個屬性巫延,這樣會讓編譯器少生成一些互斥加鎖代碼效五,可以提高效率。
2.readwrite與readonly
readwrite:這個屬性是默認的情況炉峰,會自動為你生成存取器畏妖。
readonly:只生成getter不會有setter方法。
readwrite疼阔、readonly這兩個屬性的真正價值戒劫,不是提供成員變量訪問接口,而是控制成員變量的訪問權(quán)限婆廊。
3.strong與weak
strong:強引用迅细,也是我們通常說的引用,其存亡直接決定了所指向?qū)ο蟮拇嫱鎏粤凇H绻淮嬖谥赶蛞粋€對象的引用茵典,并且此對象不再顯示在列表中,則此對象會被從內(nèi)存中釋放宾舅。
weak:弱引用统阿,不決定對象的存亡彩倚。即使一個對象被持有無數(shù)個弱引用,只要沒有強引用指向它扶平,那么還是會被清除帆离。
strong與retain功能相似;weak與assign相似结澄,只是當對象消失后weak會自動把指針變?yōu)閚il;
4.assign哥谷、copy、retain
assign:默認類型麻献,setter方法直接賦值们妥,不進行任何retain操作,不改變引用計數(shù)赎瑰。一般用來處理基本數(shù)據(jù)類型王悍。
retain:釋放舊的對象(release),將舊對象的值賦給新對象餐曼,再令新對象引用計數(shù)為1压储。我理解為指針的拷貝,拷貝一份原來的指針源譬,釋放原來指針指向的對象的內(nèi)容集惋,再令指針指向新的對象內(nèi)容。
copy:與retain處理流程一樣踩娘,先對舊值release刮刑,再copy出新的對象,retainCount為1.為了減少對上下文的依賴而引入的機 制养渴。我理解為內(nèi)容的拷貝雷绢,向內(nèi)存申請一塊空間,把原來的對象內(nèi)容賦給它理卑,令其引用計數(shù)為1翘紊。對copy屬性要特別注意:被定義有copy屬性的對象必須要 符合NSCopying協(xié)議,必須實現(xiàn)- (id)copyWithZone:(NSZone *)zone方法藐唠。
也可以直接使用:
使用assign: 對基礎數(shù)據(jù)類型 (NSInteger帆疟,CGFloat)和C數(shù)據(jù)類型(int, float, double, char, 等等)
使用copy: 對NSString
使用retain: 對其他NSObject和其子類
5.getter setter
getter:是用來指定get方法的方法名
setter:是用來指定set訪求的方法名
在@property的屬性中,如果這個屬性是一個BOOL值宇立,通常我們可以用getter來定義一個自己喜歡的名字踪宠,例如:
@property (nonatomic, assign, getter=isValue) boolean value;
@property (nonatomic, assign, setter=setIsValue) boolean value;
一,retain, copy, assign區(qū)別
假設你用malloc分配了一塊內(nèi)存,并且把它的地址賦值給了指針a妈嘹,后來你希望指針b也共享這塊內(nèi)存柳琢,于是你又把a賦值給(assign)了b。此時a
和b指向同一塊內(nèi)存,請問當a不再需要這塊內(nèi)存染厅,能否直接釋放它痘绎?答案是否定的,因為a并不知道b是否還在使用這塊內(nèi)存肖粮,如果a釋放了,那么b在使用這塊
內(nèi)存的時候會引起程序crash掉尔苦。
了解到1中assign的問題涩馆,那么如何解決?最簡單的一個方法就是使用引用計數(shù)(reference
counting)允坚,還是上面的那個例子魂那,我們給那塊內(nèi)存設一個引用計數(shù),當內(nèi)存被分配并且賦值給a時稠项,引用計數(shù)是1涯雅。當把a賦值給b時引用計數(shù)增加到
2。這時如果a不再使用這塊內(nèi)存展运,它只需要把引用計數(shù)減1活逆,表明自己不再擁有這塊內(nèi)存。b不再使用這塊內(nèi)存時也把引用計數(shù)減1拗胜。當引用計數(shù)變?yōu)?的時候蔗候,
代表該內(nèi)存不再被任何指針所引用,系統(tǒng)可以把它直接釋放掉埂软。
上面兩點其實就是assign和retain的區(qū)別锈遥,assign就是直接賦值,從而可能引起1中的問題勘畔,當數(shù)據(jù)為int, float等原生類型時所灸,可以使用assign。retain就如2中所述炫七,使用了引用計數(shù)爬立,retain引起引用計數(shù)加1, release引起引用計數(shù)減1,當引用計數(shù)為0時诉字,dealloc函數(shù)被調(diào)用懦尝,內(nèi)存被回收。
copy是在你不希望a和b共享一塊內(nèi)存時會使用到壤圃。a和b各自有自己的內(nèi)存陵霉。
atomic和nonatomic用來決定編譯器生成的getter和setter是否為原子操作。在多線程環(huán)境下伍绳,原子操作是必要的踊挠,否則有可能引起錯誤的結(jié)果。加了atomic,setter函數(shù)會變成下面這樣:
if (property != newValue) {
[property release];
property = [newValue retain];
}
二,深入理解一下(包括autorelease)1. retain之后count加一效床。alloc之后count就是1睹酌,release就會調(diào)用dealloc銷毀這個對象。
如果 retain剩檀,需要release兩次憋沿。通常在method中把參數(shù)賦給成員變量時需要retain。
例如:
ClassA有 setName這個方法:
-(void)setName:(ClassName *) inputName
{
name = inputName;
[name retain]; //此處retian沪猴,等同于[inputName retain],count等于2
}
調(diào)用時:
ClassName *myName = [[ClassName alloc] init];
[classA setName:myName]; //retain count == 2
[myName release]; //retain count==1辐啄,在ClassA的dealloc中release name才能真正釋放內(nèi)存。
- autorelease 更加tricky运嗜,而且很容易被它的名字迷惑壶辜。我在這里要強調(diào)一下:autorelease不是garbage collection,完全不同于Java或者.Net中的GC担租。
autorelease和作用域沒有任何關系砸民!
autorelease 原理:
a.先建立一個autorelease pool
b.對象從這個autorelease pool里面生成。
c.對象生成 之后調(diào)用autorelease函數(shù)奋救,這個函數(shù)的作用僅僅是在autorelease pool中做個標記岭参,讓pool記得將來release一下這個對象。
d.程序結(jié)束時菠镇,pool本身也需要rerlease, 此時pool會把每一個標記為autorelease的對象release一次冗荸。如果某個對象此時retain count大于1,這個對象還是沒有被銷毀利耍。
上面這個例子應該這樣寫:
ClassName *myName = [[[ClassName alloc] init] autorelease];//標記為autorelease
[classA setName:myName]; //retain count == 2
[myName release]; //retain count==1蚌本,注意,在ClassA的dealloc中不能release name隘梨,否則release pool時會release這個retain count為0的對象程癌,這是不對的。
記住一點:如果這個對象是你alloc或者new出來的轴猎,你就需要調(diào)用release嵌莉。如果使用autorelease,那么僅在發(fā)生過retain的時候release一次(讓retain count始終為1)捻脖。
3 xcode 中的新標記 strong weak
strong 用來修飾強引用的屬性锐峭;對應以前retain
weak 用來修飾弱引用的屬性;對應以前的assign