iOS 屬性修飾符的區別

來源:互聯網
上載者:User

標籤:

前言
iOS5 之前 所有的 開發都需要開發人員自己控制自己的對象的引用和釋放。使用的修飾符是 assign、copy、retain
iOS5 之後,Apple 推出了ARC(自動引用計數)機制,推出了新的修飾符替代之前的修飾符 strong、weak

 

簡單說明
1:ARC環境下,strong代替retain.weak代替assign
2:weak的作用:在ARC環境下,,所有指向這個對象的weak指標都將被置為nil。這個T特性很有用,相信很多開發人員都被指標指向已釋放的對象所造成的EXC_BAD_ACCESS困擾過,使用ARC以後,不論是strong還是weak類型的指標,都不會再指向一個已經銷毀的對象,從根本上解決了意外釋放導致的crash。 3:assign的作用:簡單賦值,不改變引用計數,對基礎資料類型 (例如NSInteger,CGFloat)和C資料類型(int, float, double, char, 等) 適用單一資料型別
4:copy的作用:建立一個索引計數為1 的對象,然後釋放舊對象
5:strong的作用:在ARC環境下,只要某一對象被一個strong指標指向,該對象就不會被銷毀。如果對象沒有被任何strong指標指向,那麼就會被銷毀。在預設情況下,所有的執行個體變數和局部變數都是strong類型的。可以說strong類型的指標在行為上跟非ARC下得retain是比較相似的
6:retain的作用:在非ARC時代,你需要自己retain一個想要保持的對象,ARC環境下就不需要了。現在唯一要做的就是用一個指標指向這個對象,只要指標沒有被重設為空白,對象就會一直在堆上。當指標指向新值的時候,原來的對象就會被release一次。這對執行個體變數,sunthesize的變數或者是局部變數都是實用的。

 

舉例說明

1: @property (nonatomic, assign) NSString *title; 

什麼是assign,copy,retain之間的區別? 

assign: 簡單賦值,不更改索引計數(Reference Counting)。 

copy: 建立一個索引計數為1的對象,然後釋放舊對象 

retain:釋放舊的對象,將舊對象的值賦予輸入對象,再提高輸入對象的索引計數為1 

2: weak 和strong的區別:

 (weak和strong)不同的是 當一個對象不再有strong類型的指標指向它的時候 它會被釋放  ,即使還有weak型指標指向它。

一旦最後一個strong型指標離去 ,這個對象將被釋放,所有剩餘的weak型指標都將被清除。

可能有個例子形容是妥當的。

想象我們的對象是一條狗,狗想要跑掉(被釋放)。

strong型指標就像是栓住的狗。只要你用牽繩掛住狗,狗就不會跑掉。如果有5個人牽著一條狗(5個strong型指標指向1個對象),除非5個牽繩都脫落 ,否著狗是不會跑掉的。

weak型指標就像是一個小孩指著狗喊到:“看!一隻狗在那” 只要狗一直被栓著,小孩就能看到狗,(weak指標)會一直指向它。只要狗的牽繩脫落,狗就會跑掉,不管有多少小孩在看著它。

只要最後一個strong型指標不再指向對象,那麼對象就會被釋放,同時所有的weak型指標都將會被清除。

 

使用情境

1: 使用assign: 對基礎資料類型 (NSInteger,CGFloat)和C資料類型(int, float, double, char, 等等) 

2: 使用copy: 對NSString 

3: 使用retain: 對其他NSObject和其子類 

4: strong 和weak

strong 用來修飾強引用的屬性;

@property (strong) SomeClass * aObject;

對應原來的
@property (retain) SomeClass * aObject; 和 @property (copy) SomeClass * aObject;

weak 用來修飾弱引用的屬性;
@property (weak) SomeClass * aObject;
對應原來的

@property (assign) SomeClass * aObject;

5: nonatomic關鍵字: 

atomic是Objc使用的一種線程保護技術,基本上來講,是防止在寫未完成的時候被另外一個線程讀取,造成資料錯誤。而這種機制是耗費系統資源的,所以在iPhone這種小型裝置上,如果沒有使用多線程間的通訊編程,那麼nonatomic是一個非常好的選擇。 

 

 

 

 

補充基礎知識

IOS的對象都繼承於NSObject, 該對象有一個方法:retainCount ,記憶體引用計數。 引用計數在很多技術都用到: window下的COM組件,多線程的訊號量,讀寫鎖,思想都一樣。


(一般情況下: 後面會討論例外情況)
alloc 對象分配後引用計數為1
retain 對象的引用計數+1
copy copy 一個對象變成新的對象(新記憶體位址) 引用計數為1 原來對象計數不變

release 對象引用計數-1 如果為0釋放記憶體
autorelease 對象引用計數-1 如果為0不馬上釋放,最近一個個pool時釋放
NSLog(@"sMessage retainCount:%u",[sMessage retainCount]);

記憶體管理的原則就是最終的引用計數要平衡,
如果最後引用計數大於0 則會記憶體泄露
如果引用 計數等於0還對該對象進行操作,則會出現記憶體訪問失敗,crash 所以盡量設定為nil
這兩個問題都很嚴重,所以請一定注意記憶體釋放和不用過後設定為nil

 

成員變數與屬性
實際情況並非上面那麼簡單,你可能需要在一個函數裡調用另一個函數分配的變數這時候
有兩個選擇: 類成員變數和使用屬性
@interface TestMem: NSObject {
TestObject *m_testObject ; // 成員變數
TestObject *testObject; //成員變數
}
成員變數與上面的記憶體管理是一致的,只是在不同的函數裡要保持引用計數加減的平衡
所以要你要每次分配的時候檢查是否上次已經分配了。是否還能調用
什麼時候用屬性?
1. 把成員做為public.
2. outlet 一般聲明為屬性( 這個記憶體於系統控制,但我們還是應該做一樣操作,後面會講)
3. 如果很多函數都需要改變這個對象 ,或這個函數會觸發很多次,建議使用屬性。我們看看屬性函數展開後是什麼樣子:

// assign
-(void)setTestObject :(id)newValue{
testObject= newValue;
}
// retain
-(void)setTestObject :(id)newValue{
if (testObject!= newValue) {
[testObject release];
testObject= [newValue retain];
}
}
// copy
-(void)setTestObject :(id)newValue{
if (testObject != newValue) {
[testObject release];
testObject = [newValue copy];
}
}
asssign 相于于指標賦值,不對引用計數進行操作,注意原對象不用了,一定要把這個設定為nil
retain 相當於對原對象的引用計數加1
copy 不對原對象的引用計數改變,產生一個新對象引用計數為1
注意:
self.testObject 左值調用的是setTestObject 方法. 右值為get方法,get 方法比較簡單不用說了
而 真接testObject 使用的是成員變數
self.testObject = [[testObject alloc] init]; // 錯 reatin 兩次
testObject = [NSArray objectbyindex:0]; //錯 不安全,沒有retain 後面release會出錯
如果testObject已有值也會mem leak

 

自動管理對象
IOS 提供了很多static(+) 建立對象的類方法,這些方面是靜態,可以直接用類名
調用如:
NSString *testString = [NSString stringWithFormat:@"test" ];
testString 是自動管理的對象,你不用relese 他,他有一個很大的retain count, release後數字不變。

例外
有一些通過alloc 產生的對象相同是自動管理的如:
NSString *testString = [[NSString alloc] initWithString:@"test1"];
retain count 同樣是很大的數,沒辦法release
但為了代碼對應,還是應該加上[ testString release];
不然xcode的Analyze 會認識記憶體leak, 但Instruments leak 工具檢測是沒有的

 

Cocoa不同記憶體管理環境下的autorelease
H 混合記憶體管理環境:垃圾收集法(Garbage Collection)+索引計數法(Reference Counting)
雖然大多數情況下混合實境世界是不被推薦的,但是如果在這個情況下,autorelease需要注意以下事項:
垃圾收集混合實境世界下:應該使用drain方法,因為release在GC模式下沒有意義
索引計數環境下:drain和release對於autoreleasepool(自動釋放池)的效果相同

對autorelease的誤解
A Cocoa的記憶體管理分為 索引計數法(Reference Counting/ Retain Count)和 垃圾收集法(Garbage Collection)。而iPhone上目前只支援前者,所以autorelease就成為很多人的“捷徑”。
但是!autorelease其實並不是“自動釋放”,不像垃圾收集法,對對象之間的關係偵測後發現垃圾-刪除。但是autorelease其實是“延後釋放”,在一個運行周期後被標記為autorelease會被釋放掉。
切記小心使用autorelease,理解autorelease,防止在你還需要該對象的時候已經被系統釋放掉了。

Interface Builder參與的記憶體管理問題
要點:
如果一個變數在類中被定義為了 IBOutlet 那麼你無需對其進行執行個體化,xib載入器會對其初始化。
如果一個變數在類中被定義為了 IBOutlet 那麼你必須負責將其釋放。xib載入器不會幫忙的… …
*切不要初始化兩回,記憶體會溢出,而且對象鎖定也會出錯。

關於索引計數(Reference Counting)的問題

1. *retain值 = 索引計數//(Reference Counting)

 

NSArray對象會retain(retain值加一)任何數組中的對象。當NSArray被卸載(dealloc)的時候,所有數組中的對象會被執行一次釋放(retain值減一)。不僅僅是NSArray,任何收集類(Collection Classes)都執行類似操作。例如NSDictionary,甚至UINavigationController。
Alloc/init建立的對象,索引計數為1。無需將其再次retain。
[NSArray array]和[NSDate date]等“方法”建立一個索引計數為1的對象,但是也是一個自動釋放對象。所以是本地臨時對象,那麼無所謂了。如果是打算在全Class中使用的變數(iVar),則必須retain它。
預設的類方法傳回值都被執行了“自動釋放”方法。(*如上中的NSArray)
在類中的卸載方法“dealloc”中,release所有未被平衡的NS對象。(*所有未被autorelease,而retain值為1的)

NSString的記憶體管理
如下執行個體:

1. aString = @"I am a string that 2 years old, man!";

 

這種情況下,字串儲存和管理由系統做,我們不用操心。

aString = [NSString stringWithFormat:@"I am a string that %d years old, man!",2];

 

第二種情況下,我們需要去retain和release這個字串,系統不管。

Objective-C記憶體管理
你初始化(alloc/init)的對象,你需要釋放(release)它。例如:

NSMutableArray aArray = [[NSArray alloc] init];後,需要

[aArray release];

 

2,你retain或copy的,你需要釋放它。例如:

[aArray retain]

後,需要

[aArray release];

 

3,被傳遞(assign)的對象,你需要斟酌的retain和release。例如:

obj2 = [[obj1 someMethod] autorelease];

 

對象2接收對象1的一個自動釋放的值,或傳遞一個基礎資料型別 (Elementary Data Type)(NSInteger,NSString)時: 你或希望將對象2進行retain,以防止它在被使用之前就被自動釋放掉。但是在retain後,一定要在適當的時候進行釋放。

為什麼不能直接調用dealloc而是release
dealloc不等於C中的free,dealloc並不將記憶體釋放,也不會將索引計數(Reference counting)降低。於是直接調用dealloc反而無法釋放記憶體。
在Objective-C中,索引計數是起決定性作用的。

 

 

 

 

 

 

iOS 屬性修飾符的區別

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.