2016-07-14 74 views
-1

我學習obj-c/swift弧系統。通過CFGetRetainCount函數打印創建實例的保留計數的日誌。爲什麼Obj-C實例有1個保留計數剛剛創建?

我希望像這樣的

let foo1 = NSObject() // foo1 retain count 1 
let foo2 = foo1  // foo1 retain count 2 
foo2 = nil    // foo1 retains count 1 
foo1 = nil    // foo1 retain count 0. release 

引用計數,但實際上..

let foo1 = NSObject() // foo1 retain count 2 
let foo2 = foo1  // foo1 retain count 3 
foo2 = nil    // foo1 retain count 2 
foo1 = nil    // foo1 retain count 1. release 

和打印保留NSObject的計數(直接)..

print(CFGetRetainCount(NSObject())) // retain count 1 

基本上,NSObject的( )有1個保留計數。並釋放對象時保持數達到2

我知道增加保留計數時實例強烈的聯繫。但是當保留計數變爲1而不是0時,剛剛創建的實例有1個保留計數和釋放實例。這些現象的原因是什麼?

+2

因爲'foo1','foo2'是常量,所以你的代碼甚至不能編譯*。即使你將它們聲明爲變量,你也不能給它們分配'nil'。你真的測試了什麼? –

+0

我從來不認爲CFGetRetainCount可以告訴我關於對象保留數量的信息。嘗試簡單的代碼:var foo1:NSNumber? = NSNumber(value:0) print(CFGetRetainCount(foo1))。它的打印量非常大 – larva

+1

您正在詢問關於代碼的問題。發佈您所詢問的代碼並不是您現場製作的代碼,這是很平常的禮貌。 – gnasher729

回答

2

我學習OBJ-C/SWIFT弧系統。

如果您試圖瞭解ARC和保留計數如何在較高級別上工作,那麼您的方向會錯誤。見hereherehere

什麼是這些現象的原因是什麼?

在編譯器中ARC是一個非常複雜的系統,其底層有許多優化層。很難理解實際的保留計數值。此外,它受優化級別的影響。

如果你真的想更深的潛水這裏在斯威夫特一個paper on ARC

2

TL; DR要登錄可能會影響結果的方式,你可能會得到登錄時臨時所有權,因此由1

以下的答案必須增加你所有的打印效果,是因爲你的簡化不應該在retainCount中真正擔心實際價值。

保留計數保持計數給定對象有多少引用(所有者)。 創建時,只有一個所有者,因此保留計數設置爲1.每次對象獲得新的所有者(retain)時,保留計數都會增加1。每次對象丟失並且所有者(release)保留計數減1。

請注意,retainCount永遠不會達到零。如果所有者的數量爲1,並且您失去了所有者,則對象被釋放,則計數不會減少。在斯威夫特

@implementation TestObject 

- (instancetype)init { 
    TestObject *result = [super init]; 

    NSLog(@"Retain count after creation: %@", @(self.retainCount)); 

    return result; 
} 

- (instancetype)retain { 
    TestObject *result = [super retain]; 
    NSLog(@"Retain count after retain: %@", @(self.retainCount)); 

    return result; 
} 

- (oneway void)release { 
    NSLog(@"Retain count before release: %@", @(self.retainCount)); 

    [super release]; 
} 

- (void)dealloc { 
    NSLog(@"Retain count before dealloc: %@", @(self.retainCount)); 
    [super dealloc]; 
} 

@end 

,並用它來代替你的NSObject

爲了更好的測試中,我創建了一個OBJ-C級,不ARC編譯

var foo1: TestObject? = TestObject() 
print("#") 
print(CFGetRetainCount(foo1)) 
var foo2 = foo1 
print("#") 
print(CFGetRetainCount(foo1)) 
foo2 = nil 
print("#") 
print(CFGetRetainCount(foo1)) 
foo1 = nil 

,導致:

Retain count after creation: 1 
# 
Retain count after retain: 2 
2 
Retain count before release: 2 
Retain count after retain: 2 
# 
Retain count after retain: 3 
3 
Retain count before release: 3 
Retain count before release: 2 
# 
Retain count after retain: 2 
2 
Retain count before release: 2 
Retain count before release: 1 
Retain count before dealloc: 1 

這基本上是你所期望的,但有額外的保留和當您將對象傳遞給函數時獲得臨時所有權時,會在每個CFGetRetainCount周圍發佈。

這是爲什麼你永遠不應該讀取retainCount的值的例子之一。它沒有調試值,這在documentation中也有提及。

0

總之:它至少是1,因爲當保留計數變爲0時,對象消失(因此沒有對象詢問其保留計數是多少)。

較長的答案可能是這個視頻我做了一個朋友很久以前的事:https://www.youtube.com/watch?v=cBN--I31Xjo

不過說真的,如果你使用ARC,你不應該看的保留計數。 ARC會根據需要插入保留,並且ARC在此時保留對象5次是完全正確的,只要它稍後再釋放它5次。

這與-retainCountCFGetRetainCount()問題:由於保留數的整點是共享的所有權,你不應該關心還有誰擁有一個參考,你應該只關心你的代碼有多少引用認爲,它正確地給他們通過確保它沒有循環強有力的參考。

相關問題