iOS 下ARC關於記憶體管理的引用計數問題

2021-07-13 19:38:16 字數 3593 閱讀 2043

arc有效時所有型別都必須加上所有權修飾符。所有權修飾符一共有四種:

__strong 修飾符

__strong修飾符是預設修飾符,表示物件的「強引用」,強引用物件在超出其作用域時將會被廢棄,引用的物件釋放。

id __strong obj1 = [[nsobject alloc]init];

id __strong obj2 = obj1;

obj1 = nil;

/*** obj1 = nil, obj2 != nil**/

uiview *view1 = [[uiview alloc]init];

uiview *view2 = view1;

view1.alpha = 0.4;

view2.alpha = 0.5;

/*** view1.alpha = 0.5, view2.alpha = 0.5

**/

通過上面這段**希望大家能明白記憶體管理的思考方式。

__strong修飾符能夠對同一段記憶體進行持有,並共同管理。

obj1釋放時引用計數-1,這個時候只有obj2指向記憶體,因為是強引用,所以這個時候引用計數仍為1,所以記憶體並沒有釋放。

view1和view2共同管理同一段記憶體,所以當view2修改以後,view1的值也會進行變化,因為指向同一段記憶體。

__weak 修飾符

然而strong修飾符並不能解決所有問題,當兩個物件相互強引用對方的成員變數的時候,就會發生迴圈引用,迴圈引用容易發生記憶體洩漏。所謂記憶體洩漏就是應當廢棄的物件在超出其生命週期後繼續存在。那麼在這個時候就引入了weak修飾符,「弱引用」。

因為帶weak修飾符的變數(即弱引用)不持有物件,所以在超出其作用域時,物件就會釋放,所以因為強引用而造成的迴圈引用,將其中的成員變數改為弱引用,就不會發生相同情況。

__weak修飾符還有另外乙個優點。在持有某若引用時,若該物件被廢棄,則此弱引用將自動失效且處於nil被賦值狀態(空弱引用)。如以下**所示。

nsobject __strong *obj1 = [[nsobject alloc]init];

nsobject __weak *obj2 = obj1;

obj1 = nil;

/*** obj1 = nil, obj2 = nil;

**/

通過使用weak修飾符可避免迴圈引用。通過檢查附有weak修飾符的變數是否為nil,可以判斷被賦值物件是否已廢棄。

遺憾的是,weak修飾符只能用於ios5以上及os x lion以上版本的應用程式。在ios4以及os x snow leopard的應用程式中可使用unsafe unretained修飾符來代替。

__unsafe unretained 修飾符

unsafe unretained與weak修飾符一樣不會增加引用計數,自己生成的物件不能繼續為自己所有,所以會立即釋放。

那麼unsafe unretained修飾符與weak修飾符有什麼區別呢?

比如在ios4以及os x snow leopard的應用程式中,必須使用unsafe unretained修飾符來替代weak修飾符。賦值給附有__unsafe unretained修飾符變數的物件在通過該變數使用時,如果沒有確保其存在,那麼應用就會崩潰。

__autoreleasing 修飾符

arc有效時不能使用autorelease方法,同時不能使用nsautoreleasepool類。但是,事實上arc有效時auto lease功能也是起作用的。

以下兩段**是相同的:

/*arc無效*/

nsautoreleasepool *pool = [[ns nsautoreleasepool alloc] init];

id obj = [[nsobject alloc] init];

[obj autorelease];

[pool drain];

/*arc有效*/

@autoreleasepool

/*** obj已釋放

**/

指定「@autoreleasepool塊」來替代「nsautoreleasepool類物件生成、持有以及廢棄」這一範圍。

另外,arc有效時,要通過將物件賦值給附加了autoreleasing修飾符的變數來替代呼叫autorelease方法。物件賦值給附有autoreleasing修飾符的變數等價於在arc有效時呼叫物件的autorelease方法,即物件被註冊到autoreleasepool。

也就是可以說arc有效時,用@aotureleasepool塊替代nsautoreleasepool類,用附有__autoreleasing修飾符的變數替代autorelease方法。

因為autoreleasepool範圍以塊級源**表示,提高了程式的可讀性,所以今後在arc無效時也推薦使用@autoreleaseepool塊。

另外,無論arc是否有效,除錯用的非公開函式_objc_autoreleasepoolprint()都可使用。

_objc_rootretaincount(obj)

利用這一函式可有效的幫助我們除錯註冊到autoreleasepool上的物件。

上面講解了四種修飾符,在arc有效的情況下,必須遵守一定的規則。下面就是具體的arc規則:

最後我們來看一下arc中自動引用計數的數值究竟是多少

我們來看這段**:

//retain count = 0;

和我們預期的一樣,strong修飾符使引用技術+1,而weak修飾符,並不會使修飾符+1,早超出obj的作用域以後,引用技術-1,同時釋放。

我們再來看一下用__autoreleasing修飾符向autoreleasepool註冊會怎麼樣:

@autoreleasepool 

//retain count = 0;

__autoreleasing修飾符,使引用計數+1,而在超出autoreleasepool以後則清空並釋放。

最後再來看一下在autoreleasepool中使用__weak修飾符是什麼樣的:

@autoreleasepool
在autoreleasepool中即使不使用autoreleasing修飾符,而用__weak修飾符替代,同樣將obj物件註冊到了autoreleasepool中。

iOS記憶體管理 ARC

arc是在編譯的時候插入 來確信讓物件能夠按需要來存在。arc同樣是以引用計數為基礎。你可以選擇在以檔案或者專案為單位不使用arc。但是建議盡量最好使用arc,首先,編譯器為你做記憶體管理往往比你自己要更優秀,其次,arc導致的效率損失在ui面前基本可以忽略不計。arc有以下強制規則 1.你不能顯示...

ARC下的記憶體管理

本文討論一下arc automatic referencing count 下的記憶體管理問題 例項變數是類的私有成員變數,無法被外部訪問,並且子類無法繼承。屬性以 property修飾,是封裝了getter setter方法的 成員變數 可以被外部訪問和被繼承。宣告屬性後,系統會生成乙個名為 pr...

iOS基礎之記憶體管理 一 ARC下的記憶體洩漏

arc automatic reference counting,自動引用計數 是指在記憶體管理中採取自動計數的技術。在llvm編譯器中設定arc為有效狀態,就無需再次鍵入retain或者release 蘋果官方說明換言之,滿足下面的條件就無需手動輸入retain release了 使用xcode4...