IOS中@property的屬性weak、nonatomic、strong、readonly等介紹


iOS開發中@property的屬性weak nonatomic strong readonly等介紹

//property:屬性;
//synthesize:綜合;

@property與@synthesize是成對出對出現的,可以自動生成某個類成員變量的存取方法。
在Xcode4.5以及以后的版本,@synthesize可以省略。

//atomic:原子的
//nonatomic:無原子的

1.atomic與nonatomic
atomic:默認是由該屬性的,這個屬性是為了保證程序在多線程情況,編譯器會自動生成一些互斥加鎖代碼,避免該變量的讀寫不同步問題。
nonatomic:如果該對象無需考慮多線程的情況,請加入這個屬性,這樣會讓編譯器少生成一些互斥加鎖代碼,可以提高效率。

2.readwrite與readonly
readwrite:這個屬性是默認的情況,會自動為你生成存取器。
readonly:只生成getter不會有setter方法。
readwrite、readonly這兩個屬性的真正價值,不是提供供成員變量訪問接口,而是控制成員變量的訪問權限。

3.strong與weak(弱引用)
strong:強引用,也是我們通常說的引用,其存亡直接決定了所指向對象的存亡。如果不存在指向一個對象引用,
並且此對象不在顯示在列表中,則此對象會被從內存中釋放。
weak:弱引用,不決定對象的存亡。即使一個對象被持有無數個弱引用,只要沒有強引用指向它,那么還是會被清除。
strong與retain功能相似;weak與assign相似,只是當對象消失后weak會自動把指針變為nil.

//assign:分配
//retain:保留
4.assign、copy、retain
assign:默認類型,setter方法直接賦值,不進行任何retain操作,不改變引用計數。一般用來處理基本數據類型。
retain:釋放舊的對象(release),將舊對象的值賦給新對象,再令新對象引用技術為1。我理解為指針的拷貝,拷貝一份原來
的指針,釋放原來指針指向的對象內容,再令指針指向新的對象內容。
copy:與retain處理流程一樣,先對舊值release,再copy出新的對象,retainCount為1。為了減少對上下文的依賴而引入的機制。
我理解為內容的拷貝,向內存申請一塊空間,把原來的對象內容賦給它,令其引用計數為1。對copy屬性要特別注意:被定義有
copy屬性的對象必須要符合NSCopying協議,必須實現-(id)copyWithZone:(NSZone*)zone方法。
也可以直接使用:
    使用assign:對基礎數據類型(NSInteger、CGFloat)和C數據類型(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區別

1.假設你用malloc分配了一塊內存,並且把它的地址賦給了指針a,后來你希望指針b也共享這塊內存,於是你又把a賦值給(assign)了b。
此時a和b指向同一塊內存,請問當a不再需要這塊內存,能否直接釋放它?答案是否定的,因為a並不知道b是否還在使用這塊內存,如果
a釋放了,那么b在使用這塊內存的時候會引起程序crash掉。

2.了解到1中assign的問題,那么如何解決?最簡單的一個方法就是使用引用計數(reference counting),還是上面的那個例子,我們給
那塊內存設一個引用計數,當內存被分配並且賦值給a時,引用計數是1。當把a賦值給b時引用計數增加到2。這時如果a不再使用這塊內存,
它只需要把引用計數減1,表明自己不再擁有這塊內存。b不再使用這塊內存時也把引用計數減1。當引用計數變為0的時候,代表該內存不再
被任何指針所引用,系統可以把它直接釋放掉。

3.上面兩點其實就是assign和retain的區別,assign就是直接賦值,從而可能引起1中的問題,當數據為int,float等原生類型時,可以使用assign。
retain就如2中所述,使用了引用計數,retain引起引用計數加1,release引起引用技術減1,當引用計數為0時,dealloc函數被調用,內存被收回。

4..atomic和nonatomic用來決定編譯器的生成getter和setter是否為原子操作。在多線程環境下,原子操作是必要的,否則有可能引起錯誤結果。
加了atomic,setter函數會變成下面這樣:

      if(property != newValue){
      [property release];
      property=[newValue retain];
      }

二、深入理解一下(包括antorelease)
1.retain之后count加1。alloc之后count就是1,release就會調用dealloc銷毀這個對象。
如果retain,需要release兩次。通常在method中把參數賦給成員變量時需要retain.
例如:

classA有setName這個方法:
-(void)setName(ClassName *) inputName
{
    name=inputName;
    [name retain];//此處retain,等同於[inputName retain],count等於2
}

調用時:

ClassName *myName=[[ClassName alloc] init];
[[classA setName:myName]; //retain count == 2
[myName release]; //retain count==1,在ClassA的dealloc中release name才能真正釋放內存。]

 2、autorelease更加tricky,而且很容易被它的名字迷惑。我在這里要強調一下:autorelease不是garbage collection,
完全不同於Java或者.Net中的GC。
autorelease和作用域沒有任何關系!
autorelease 原理:
a.先建立一個autorelease pool
b.對象從這個autorelease pool里面生成。
c.對象生成 之后調用autorelease函數,這個函數的作用僅僅是在autorelease pool中做個標記,讓pool記得將來release一下這個對象。
d.程序結束時,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出來的,你就需要調用release。
                如果使用autorelease,那么僅在發生過retain的時候release一次(讓retain count始終為1)。
3 xcode 中的新標記 strong weak
strong 用來修飾強引用的屬性;對應以前retain
 
weak 用來修飾弱引用的屬性;對應以前的assign。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM