2014-10-18 79 views
0

請檢查下面的代碼:爲什麼在原始NSString對象被釋放後NSString的lowercaseString沒有被釋放?

CFUUIDRef uuid=CFUUIDCreate(kCFAllocatorDefault); 
NSString *strUuid=(NSString *)CFUUIDCreateString(kCFAllocatorDefault,uuid); 
NSString *lowerUuid=[strUuid lowercaseString]; 
NSLog(@"strUuid retainCount:%tu",[strUuid retainCount]); 
CFRelease(strUuid); 
CFRelease(uuid); 
NSLog(@"lowerUuid retainCount:%tu",[lowerUuid retainCount]); 
NSLog(@"lowerUuid:%@",lowerUuid); 

運行這段代碼在非弧項目,輸出將是:

strUuid retainCount:1 
lowerUuid retainCount:1 
lowerUuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 

lowercaseString是的NSString的一個屬性,它的定義是:

@property (readonly, copy) NSString *lowercaseString; 

所以有理由推斷,如果原始NSString對象被釋放,則在NSString的dealloc方法中將釋放lowercaseString屬性。 但是爲什麼在上面的代碼中,即使原始strUuid被釋放後,lowerUuid仍然存在?

+0

我不認爲這是一個合理的推論。 'copy'屬性可能意味着返回的值是原始字符串的副本,並附有自己的保留計數。 – 2014-10-18 01:31:53

回答

3

首先,標準免責聲明:不要看-retainCount。它有許多需要注意的地方,並且不可信任任何有用的東西。

這就是說:你的推論沒有描述發生了什麼。當你詢問strUuid-lowercaseString時,你沒有得到某種「孩子」對象。由此產生的小寫字符串是一個完全獨立的對象,具有自己的內部保留計數。 (原始字符串可能會保留自己對小寫字符串的引用,但這不是您的擔心。)

在您的代碼片段中,在標準內存管理約定下,通常發生的情況是[strUuid lowercaseString]返回一個「autoreleased」對象。因此,即使原始字符串被釋放,返回給您的字符串仍然有效:(a)至少,直到自動釋放池清理完畢或(b)在其上次實際訪問後,取決於ARC狀態該項目。

+1

很好的答案。擴大一點:僅僅因爲某些東西被聲明爲「@屬性」並不意味着它是某種從屬對象。 readonly屬性只是一個getter方法,可以返回其實現者所需的任何東西。 – rickster 2014-10-18 04:49:04

+0

東西被聲明爲@property並不意味着它是某種下屬對象!這就是困惑我的觀點,我曾經認爲一個財產必須是一個超級對象。謝謝! – 2014-10-19 06:13:48