36.不要使用retainCount

《編寫高質(zhì)量iOS與OS X代碼的52個有效方法》--第五章 第36條
(ps:此乃讀書筆記,加深記憶,僅供大家參考)


第36條 不要使用retainCount

NSObject協(xié)議中定義了下列方法,用于查詢對象當前的保留計數(shù):

- (NSUInteger)retainCount

然而ARC已經(jīng)將此方法廢棄了。若在不啟用ARC的環(huán)境下編程,那么扔可調(diào)用此方法,所以還是必須講清楚為何不應使用此方法。

這個方法看上去似乎挺合理的、挺有用的。但問題在于,保留計數(shù)的絕對值一般都與開發(fā)者所應留意的事情完全無關。即便是在調(diào)試時才調(diào)用此方法,通常也還是無所助益的。

此方法之所以無用,其首要原因在于:它所返回的保留計數(shù)只是某個給定時間點上的值。該方法并未考慮到系統(tǒng)會稍后把自動釋放池清空,因而不會將后續(xù)的釋放操作從返回值里減去,這樣的話,此值就未必能真實反映實際的保留計數(shù)了。

有下面這段代碼:

NSString *stirng = @"Some string";
NSLog(@"string retainCount = %lu", [stirng retainCount]);

NSNumber *numberI = @1;
NSLog(@"numberI retainCount = %lu", [numberI retainCount]);

NSNumber *numberF = @3.14f;
NSLog(@"numberF retainCount = %lu", [numberF retainCount]);

在64位Mac OS X 10.8.2系統(tǒng)中,用Clang4.1編譯后,這段代碼輸出的消息如下:

string retainCount = 18446744073709551615
numberI retainCount = 9223372036854775807
numberF retainCount = 1

第一個對象的保留計數(shù)是2^64 - 1,第二個對象的保留計數(shù)是2^63 - 1.由于二者皆為“單例對象”(singleton object),所以其保留計數(shù)都很大。系統(tǒng)會盡可能把NSStirng實現(xiàn)成單例對象。如果字符串像本例所舉的這樣,是個編譯常量(compile-time constant),那么就可以這樣來實現(xiàn)了。在這用情況下,編譯器會把NSString對象所表示的數(shù)據(jù)放到應用程序的二進制文件里,這樣的話,運行程序時就可以直接用了,無須再創(chuàng)建NSString對象。NSNumber也類似,它使用了一種叫做“標簽指針”(tagged pointer)的概念來標注特定類型的數(shù)值。這種做法不使用NSNumber對象,而是把與數(shù)值有關的全部消息都放在指針值里面。運行期系統(tǒng)會在消息派發(fā)(參見第11條)期間檢測到這種標簽指針,并對它執(zhí)行相應操作,使其行為看上去和真正的NSNumber對象一樣。這種優(yōu)化只在某些場合使用,比如范例中的浮點數(shù)對象就沒有優(yōu)化,所以其保留計數(shù)就是1。

另外,像剛才所說的那種單例對象,其保留計數(shù)絕對不會變。這種對象的保留及釋放操作都是“空操作”(no-op)。

那么,只為了調(diào)試而使用retainCount方法行不行呢?即便只為調(diào)試,此方法也不是很有用。以下列代碼為例:

id object = [self createObject];
[opaqueObject doSomethingWithObject:object];
NSLog(@"retainCount = %lu", [object retainCount]);

object的保留計數(shù)是多少呢?這個計數(shù)可以是任意值?!癲oSomethingWithObject:”方法也許會將對象加到多個collectin中,而這些collection均會保留此對象。這個方法還可能會多次保留并自動釋放此對象,而其中某些自動釋放操作要留待系統(tǒng)稍后清空自動釋放池時才執(zhí)行。因此,保留計數(shù)的實際值就不是那么有用了。

要點

  • 對象的保留計數(shù)看似有用,實則不然,因為任何給定時間點上的“絕對保留計數(shù)”(absolute retain count)都無法反映對象生命期的全貌。
  • 引入ARC之后,retainCount方法就正式廢止了,在ARC下調(diào)用該方法會導致編譯器報錯。
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 29.理解引用計數(shù) Objective-C語言使用引用計數(shù)來管理內(nèi)存,也就是說,每個對象都有個可以遞增或遞減的計數(shù)...
    Code_Ninja閱讀 1,741評論 1 3
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結起來就是把...
    Dove_iOS閱讀 27,622評論 30 472
  • 內(nèi)存管理 簡述OC中內(nèi)存管理機制。與retain配對使用的方法是dealloc還是release,為什么?需要與a...
    丶逐漸閱讀 2,081評論 1 16
  • 第 23 條:通過委托與數(shù)據(jù)源協(xié)議進行對象間通信 Objective-C 可以使用 “委托模式”(Delegate...
    德山_閱讀 927評論 0 2
  • 內(nèi)存管理是程序在運行時分配內(nèi)存、使用內(nèi)存,并在程序完成時釋放內(nèi)存的過程。在Objective-C中,也被看作是在眾...
    蹲瓜閱讀 3,363評論 1 8

友情鏈接更多精彩內(nèi)容