在你繼續(xù)深入學習之前,請停下腳步弄清這些問題。如果你是新手,這個教程不要希望一次能看的非常透徹,學一定階段反回來再看看又會有新的體會的。
1. c,c++ background
很多人問 “沒有任何語言基礎,我不想學c直接學objective-c”
這里簡單幾句,objc 90%代碼是c、眾多開源代碼是c,c++。你不學好c在unix世界里只能是個二流開發(fā)者!也許說得過于嚴厲,不過自己斟酌把。
2. Runtime(運行時)
Objective-c是動態(tài)語言, 很多新手或者開發(fā)人員常常被Runtime這個東西所迷惑。而恰恰這是一個非常重要的概念。 為什么重要呢!?我可以這么問:“如果讓你(設計、)實現(xiàn)一個計算機語言,你要如何下手?” 很少程序員這么思考過。但是這么一問,就會強迫你從更高層次思考(1)以前的問題了。 注意我這句話‘設計’括起來了,稍微次要點,關鍵是實現(xiàn)。
我把實現(xiàn)分成3鐘不同的層次:
好了上面說著這么多,我們再返回來看objective-c. 現(xiàn)在你是不是能理解這樣的語句了呢?
看似很簡單的語句,但是為了讓語言實現(xiàn)這個能力,語言開發(fā)者要付出很多努力實現(xiàn)runtime環(huán)境。這里運行時環(huán)境處理了弱類型、函數(shù)存在檢查工作。runtime會檢測注冊列表里是否存在對應的函數(shù),類型是否正確,最后確定下來正確的函數(shù)地址,再進行保存寄存器狀態(tài),壓棧,函數(shù)調用等等實際的操作。
在c,c++年代去完成這個功能是非常麻煩的,但是動態(tài)語言卻非常簡單。
關于執(zhí)行效率問題。 “靜態(tài)語言執(zhí)行效率要比動態(tài)語言高”,這句沒錯。因為一部分cpu計算損耗在了runtime過程中。而靜態(tài)語言生成的機器指令更簡潔。正因為知道這個原因,所以開發(fā)語言的人付出很大一部分努力為了保持runtime小巧上。所以objecitve-c是c的超集+一個小巧的runtime環(huán)境。 但是,換句話說,從算法角度考慮,這點復雜度不算差別的,Big O notation結果不會有差別。( It's not log(n) vs n^2 )
簡單理解:“Runtime is everything between your each function call.”
Runtime好比objective-c的靈魂。很多東西都是在這個基礎上出現(xiàn)的。所以它是指的你花功夫去理解的。
3. thread
"thread synchronization another notorious trouble!"
記不記得上學時候學得操作系統(tǒng)這門課,里面都會有專門一章介紹任務調度和生產(chǎn)者消費者的問題。 這就是為了今后使用進程、線程開發(fā)打基礎。概念很簡單,但是心知肚明的人很少。難點在synchronization(同步),因為1. There is no 100% deadlock detection algorithm. If there is, no deadlock at all. 2. 往往這類錯誤很隱晦,靜態(tài)分析很難找到。 3. 抽象度較高需要經(jīng)驗去把握。
總體來說,我見到的在這方面的問題可以分為一下幾點:
4. runloop
現(xiàn)在說說runloop為何會成為cocoa開發(fā)中迷惑的點。因為很多新手沒有從動態(tài)角度看它。 首先回想一下第2點介紹的runtime的概念。 接著我出一個題思考一下。
現(xiàn)在我有一個程序片段如下:
現(xiàn)在要求,做某些設計,使得當這個線程運行的同時,還可以從其它線程里往它里面隨意增加或去掉不同的計算任務。 這,就是NSRunloop的最原始的開發(fā)初衷。讓一個線程的計算任務更加靈活。 這個功能在c, c++里也許可以做到但是非常難,最主要的是因為語言能力的限制,以前的程序員很少這么去思考。
好,現(xiàn)在我們對上面代碼做一個非常簡單的進化:
注意,這里沒有做線程安全處理,記住Mutable container is not thread safe.
這個簡單的擴展,讓我們看到了如何利用runtime能力讓線程靈活起來。當我們從另外線程向targetQueue和actionQueue同時加入對象和方法時候,這個線程函數(shù)就有了執(zhí)行一個額外代碼的能力。
但,有人會問,哪里有runloop? 那個是 nsrunloop? 看不出來啊。
一個線程內(nèi)這個結構就叫線程的runloop, 它和NSRunloop這個類雖然名字很像,但完全不是一個東西。以前在使用靜態(tài)語言開始時候,程序員沒有什么迷惑,因為沒有NSRunloop這個東西。 我接著來說,這個NSRunloop是如何來得。
第二段擴展代碼里面確實沒有NSRunloop這個玩意兒,我們接著做第3次改進。 這次我們的目前是把哪個動態(tài)部分抽象出來。
5. delegate, protocol
這個會列出來因為,我感覺問它的數(shù)量僅此于內(nèi)存管理部分,它們用得很頻繁,并且它們是多鐘設計模式的重要組成部分。
6. responder chain
7. Memory Reference Counting(RC) & Automatic Reference Counting(ARC)
這個也許是問得最多的問題了吧。所有這些問題往往來源于3個地方,1、不了解底層機制;2、沒有吃透規(guī)則; 3、不了解常用container的Reference Counting特性,或著說沒有下功夫去看對應文檔。
1. 底層機制
大家是否知道從舊時代的RC到ARC機制到底意味著什么呢? 為什么ARC從開發(fā)速度,到執(zhí)行速度和穩(wěn)定性都要優(yōu)于rc?
開發(fā)速度不言而喻,你少寫很多release代碼,甚至很少去操心這部分。
執(zhí)行速度呢?這個還要從runtime說起,還記得我在第2點說得一句話么:“Runtime is everything between your each function call.”
RC是一個古老的內(nèi)存管理哲學,誰分配誰釋放。通過counting來計數(shù)到底該資源有幾個使用者。道理很簡單,但是往往簡單的東西人卻會犯錯。從來沒有一個程序員可以充滿信心的說,我寫得代碼從來沒有過內(nèi)存泄露。這樣來看,我們就更需要讓程序可以自己處理這個管理機制,這就需要把這個機制放到runtime里。
所以RC->ARC就是把內(nèi)存管理部分從普通開發(fā)者的函數(shù)中移到了函數(shù)外的runtime中。因為runtime的開發(fā)原型簡單,邏輯層次更高,所以做這個開發(fā)和管理出錯的概率更小。實際上編譯器開發(fā)人員對這部分經(jīng)過無數(shù)次測試,所以可以說用arc幾乎不會出錯。另外由于編譯的額外優(yōu)化,使得這個部分比程序員自己寫得代碼要快速很多。而且對于一些通用的開發(fā)模式,例如autorelease對象,arc有更優(yōu)秀的算法保證autoreleasepool里的對象更少。
2. RC規(guī)則
首先說一下rc是什么,r-Reference參照,引用 c-counting計數(shù), rc就是引用計數(shù)。俗話說就是記錄使用者的數(shù)量。 例如現(xiàn)在我有一個房間空著,大家可以進去隨意使用,但是你進門前,需要給門口的計數(shù)牌子+1, 出門時候-1。 這時候這個門口的牌子就是該房間里的人數(shù)。一但這個牌子變?yōu)椋拔揖涂梢园逊块g關閉。
這個規(guī)則可以讓NSObject決定是不是要釋放內(nèi)存。當一個對象alloc時候,系統(tǒng)分配其一塊內(nèi)存并且object自動計數(shù)retainCount=1 這時候每當[object retain]一次retainCount+1(這里雖然簡寫也是rc不過是巧合或者當時開發(fā)人員故意選的retain這個詞吧)每次[object release]時候retainCount-1 當retainCount==0時候object就真正把這快內(nèi)存還給系統(tǒng)。
3. 常用container的Reference Counting特性
這個規(guī)則很簡單把。但是這塊確實讓新手最頭疼的地方。 問題出在,新手總想去驗證rc規(guī)則,又總是發(fā)現(xiàn)和自己的期望不符合。
無數(shù)次看到有人寫下如下句子
當然了,我也做過類似的動作,那種希望一切盡在掌握中的心態(tài)。但是你會看到其他人告訴這么做完全沒有意義。rc does not work this way. 也許這樣的暴力釋放會起作用,但是retainCount并不是用來做這個的。每個數(shù)字意味著有其它對象引用該資源,這樣的暴力釋放很容易導致程序崩潰。這個數(shù)字也許并不是你心目中的哪個。因為你很難跟蹤到底哪些對象引用的該資源。你用代碼建立的資源不光只有你的代碼才會用到,你調用的各種Framework,F(xiàn)ramework調用的Framework,都有可能改變這個資源的retainCount. 所以去驗證rc規(guī)則不是明智之舉。
你能做的就是理解規(guī)則,使用規(guī)則,讀文檔了解container的引用特性。或者干脆移到arc上面,讓runtime環(huán)境處理這些問題。
最后說一下不用arc的情況。目前情況來看,有不少第三方的庫并未支持arc,所以如果你的舊項目使用了這些庫,請檢查是否作者發(fā)布了新版本,或者你需要自己修正支持arc。
8. class heritage
9. English
10. Just trying to be smart
其實剩下這個有好幾點要說,但綜合一下把。思路有些相似
例如剛看到這個問題:
It's kind of silly. 我并不是想諷刺問問題的朋友。其實如果你真的了解了上面這些知識點,就不會再問這種問題的。 為什么不多思考一層呢,在問這個問題之前想想,到底為什么會問出這個問題? ”如果讓你給NSMutableArray實現(xiàn)一個replaceObjectAtIndex函數(shù)你會怎么寫?“ 難道連個[obj release]都考慮不到么?然后根據(jù)ARC,它到底釋放了沒不言自明了把。
其實這種問題論壇里很多的。不妨在迷惑的時候,先問問自己為什么會迷惑。
(1)這里其實很有意思,為何我用“更高層次思考”,而不是“更底層次”。作為一個編譯器和語言開發(fā)人員,面對的問題確實更底層沒錯,但是他們思考的維度更高,更抽象,這樣子。一個不算恰當?shù)谋确骄秃孟褚粋€三維世界的人處理二維世界的一條線的問題。 @import url(http://www.shnenglu.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
1. c,c++ background
很多人問 “沒有任何語言基礎,我不想學c直接學objective-c”
這里簡單幾句,objc 90%代碼是c、眾多開源代碼是c,c++。你不學好c在unix世界里只能是個二流開發(fā)者!也許說得過于嚴厲,不過自己斟酌把。
2. Runtime(運行時)
Objective-c是動態(tài)語言, 很多新手或者開發(fā)人員常常被Runtime這個東西所迷惑。而恰恰這是一個非常重要的概念。 為什么重要呢!?我可以這么問:“如果讓你(設計、)實現(xiàn)一個計算機語言,你要如何下手?” 很少程序員這么思考過。但是這么一問,就會強迫你從更高層次思考(1)以前的問題了。 注意我這句話‘設計’括起來了,稍微次要點,關鍵是實現(xiàn)。
我把實現(xiàn)分成3鐘不同的層次:
1. 傳統(tǒng)的面向過程的語言開發(fā),例如c語言。實現(xiàn)c語言編譯器很簡單,只要按照語法規(guī)則實現(xiàn)一個LALR語法分析器就可以了,編譯器優(yōu)化是非常難的topic,不在這里討論范圍內(nèi),忽略。 這里我們實現(xiàn)了編譯器其中最最基礎和原始的目標之一就是把一份代碼里的函數(shù)名稱,轉化成一個相對內(nèi)存地址,把調用這個函數(shù)的語句轉換成一個jmp跳轉指令。在程序開始運行時候,調用語句可以正確跳轉到對應的函數(shù)地址。 這樣很好,也很直白,但是。。。太死板了。everything is per-determined
2. 我們希望靈活,于是需要開發(fā)面向對象的語言,例如c++。 c++在c的基礎上增加了類的部分。但這到底意味著什么呢?我們再寫它的編譯器要如何考慮呢?其實,就是讓編譯器多繞個彎,在嚴格的c編譯器上增加一層類處理的機制,把一個函數(shù)限制在它處在的class環(huán)境里,每次請求一個函數(shù)調用,先找到它的對象, 其類型,返回值,參數(shù)等等,確定了這些后再jmp跳轉到需要的函數(shù)。這樣很多程序增加了靈活性同樣一個函數(shù)調用會根據(jù)請求參數(shù)和類的環(huán)境返回完全不同的結果。增加類機制后,就模擬了現(xiàn)實世界的抽象模式,不同的對象有不同的屬性和方法。同樣的方法,不同的類有不同的行為! 這里大家就可以看到作為一個編譯器開發(fā)者都做了哪些進一步的思考。但是。。。還是死板, 我們?nèi)匀唤衏++是static language。
3. 希望更加靈活! 于是我們完全把上面哪個類的實現(xiàn)部分抽象出來,做成一套完整運行階段的檢測環(huán)境。這次再寫編譯器甚至保留部分代碼里的sytax名稱,名稱錯誤檢測,runtime環(huán)境注冊所以全局的類,函數(shù),變量等等信息等等,我們可以無限的為這個層增加必要的功能。調用函數(shù)時候,會先從這個運行時環(huán)境里檢測所以可能的參數(shù)再做jmp跳轉。這,就是runtime。編譯器開發(fā)起來比上面更加彎彎繞。但是這個層極大增加了程序的靈活性。 例如當調用一個函數(shù)時候,前2種語言,很有可能一個jmp到了一個非法地址導致程序crash, 但是在這個層次里面,runtime就過濾掉了這些可能性。 這就是為什么dynamic langauge更加強壯。 因為編譯器和runtime環(huán)境開發(fā)人員已經(jīng)幫你處理了這些問題。
好了上面說著這么多,我們再返回來看objective-c. 現(xiàn)在你是不是能理解這樣的語句了呢?
復制代碼
|
看似很簡單的語句,但是為了讓語言實現(xiàn)這個能力,語言開發(fā)者要付出很多努力實現(xiàn)runtime環(huán)境。這里運行時環(huán)境處理了弱類型、函數(shù)存在檢查工作。runtime會檢測注冊列表里是否存在對應的函數(shù),類型是否正確,最后確定下來正確的函數(shù)地址,再進行保存寄存器狀態(tài),壓棧,函數(shù)調用等等實際的操作。
復制代碼
|
在c,c++年代去完成這個功能是非常麻煩的,但是動態(tài)語言卻非常簡單。
關于執(zhí)行效率問題。 “靜態(tài)語言執(zhí)行效率要比動態(tài)語言高”,這句沒錯。因為一部分cpu計算損耗在了runtime過程中。而靜態(tài)語言生成的機器指令更簡潔。正因為知道這個原因,所以開發(fā)語言的人付出很大一部分努力為了保持runtime小巧上。所以objecitve-c是c的超集+一個小巧的runtime環(huán)境。 但是,換句話說,從算法角度考慮,這點復雜度不算差別的,Big O notation結果不會有差別。( It's not log(n) vs n^2 )
簡單理解:“Runtime is everything between your each function call.”
Runtime好比objective-c的靈魂。很多東西都是在這個基礎上出現(xiàn)的。所以它是指的你花功夫去理解的。
3. thread
"thread synchronization another notorious trouble!"
記不記得上學時候學得操作系統(tǒng)這門課,里面都會有專門一章介紹任務調度和生產(chǎn)者消費者的問題。 這就是為了今后使用進程、線程開發(fā)打基礎。概念很簡單,但是心知肚明的人很少。難點在synchronization(同步),因為1. There is no 100% deadlock detection algorithm. If there is, no deadlock at all. 2. 往往這類錯誤很隱晦,靜態(tài)分析很難找到。 3. 抽象度較高需要經(jīng)驗去把握。
總體來說,我見到的在這方面的問題可以分為一下幾點:
1. 不知道多線程開發(fā)的幾個基點,看別人代碼越看越糊涂的。一會NSThread、一會*****、block等等。。。Apple封裝了很多線程的api, down to core多線程的結構基本是
![]()
可以看到在多線程開發(fā)中你可以選擇這幾種不同的方式。Mach是最和心的操作系統(tǒng)部分,你可以用但是沒必要,太累。
pthread靈活、輕巧,但是需要理論基礎還是開發(fā)復雜,最主要的POSIX開的線程不能使用cocoa根據(jù)apple文檔只在pthread下使用cocoa需要先detach at least one NSThread object. 這樣確定[NSThread isMultiThreaded]才可以使用。
NSThread是Mac OS 10.0后發(fā)布的多線程API較為高層,但是缺乏靈活性。
Grand Central Dispatch 10.6引入的開源多線程庫, *****介于pthread和NSThread之間。比NSThread更靈活,小巧但有不需要像pthread一樣考慮很多l(xiāng)ock的問題。而objective-c 2.0發(fā)布的新語法特性之一blocks也正是根據(jù)這種多線程需求推出的。
在你寫多線程代碼或者閱讀多線程代碼時候,心理先明確了這是那種。
2. thread和runloop造成的問題
其實thread和runloop放在以前開發(fā)者根本不太當成一個問題。因為沒有runtime能力,runloop就是固定的線程執(zhí)行l(wèi)oop。而現(xiàn)在cocoa開發(fā)新手搞不明白的太多了。 NSRunloop和NSThread啥關系?由于這個問題比較多,我單獨列到第4點里講解把。
3. thread和Reference Counting內(nèi)存管理造成的問題。
引用線程里面的方法都要放到NSAutoreleasePool里面嗎
這類問題很常見,主要原因是 NSAutoreleasePool 到底是干什么用得不明白。 NSAutoreleasePool跟thread其實關系并不顯著,它提供一個臨時內(nèi)存管理空間,好比一個沙箱,確保不會有不當?shù)膬?nèi)存分配泄露出來,在這個空間內(nèi)新分配的對象要向這個pool做一下注冊告訴:“pool,我新分配一塊空間了”。當pool drain掉或者release,它里面分配過的內(nèi)存同樣釋放掉。可見和thread沒有很大關系。但是,我們閱讀代碼的時候經(jīng)常會看到,新開線程的函數(shù)內(nèi)總是以NSAutoreleasePool開始結束。這又是為什么呢!? 因為thread內(nèi)恰好是最適合需要它的地方! 線程函數(shù)應該計算量大,時間長(supposed to be heavy)。在線程里面可能會有大量對象生成,這時使用autoreleasepool管理更簡潔。所以這里的答案是,不一定非要在線程里放NSAutoreleasePool,相對的在cocoa環(huán)境下任意地方都可以使用NSAutoreleasePool。如果你在線程內(nèi)不使用NSAutoreleasePool,要記得在內(nèi)部alloc和relase配對出現(xiàn)保證沒有內(nèi)存泄露。
這里還有一個值得提出的是autorelease. NSObject為何會有autorelease這個方法? 它是根據(jù)什么auto的?
4. mainthread和secondary thread疑惑
引用NSThread的detachNewThreadSelector和self的performSelectorOnMainThread方法有什么不同
5. Asynchronous(異步) vs. Synchronous(同步)
引用我在一個view要顯示多張web圖片,我想問一下,我是應該采用異步一個一個下載的方式,還是應該采用多線程同時下載的方式,還是2個都用,那種方式好呢?
大家可以看一下這個問題。這句有一點在我看來是非常奇怪的,因為我覺得問問題的人并不理解同步異步是什么意思。"一個一個下載的方式"是同步的行為,“多線程同時下載”是異步的行為。 都搞混了把!
4. runloop
現(xiàn)在說說runloop為何會成為cocoa開發(fā)中迷惑的點。因為很多新手沒有從動態(tài)角度看它。 首先回想一下第2點介紹的runtime的概念。 接著我出一個題思考一下。
現(xiàn)在我有一個程序片段如下:
復制代碼
|
現(xiàn)在要求,做某些設計,使得當這個線程運行的同時,還可以從其它線程里往它里面隨意增加或去掉不同的計算任務。 這,就是NSRunloop的最原始的開發(fā)初衷。讓一個線程的計算任務更加靈活。 這個功能在c, c++里也許可以做到但是非常難,最主要的是因為語言能力的限制,以前的程序員很少這么去思考。
好,現(xiàn)在我們對上面代碼做一個非常簡單的進化:
復制代碼
|
注意,這里沒有做線程安全處理,記住Mutable container is not thread safe.
這個簡單的擴展,讓我們看到了如何利用runtime能力讓線程靈活起來。當我們從另外線程向targetQueue和actionQueue同時加入對象和方法時候,這個線程函數(shù)就有了執(zhí)行一個額外代碼的能力。
但,有人會問,哪里有runloop? 那個是 nsrunloop? 看不出來啊。
復制代碼
|
一個線程內(nèi)這個結構就叫線程的runloop, 它和NSRunloop這個類雖然名字很像,但完全不是一個東西。以前在使用靜態(tài)語言開始時候,程序員沒有什么迷惑,因為沒有NSRunloop這個東西。 我接著來說,這個NSRunloop是如何來得。
第二段擴展代碼里面確實沒有NSRunloop這個玩意兒,我們接著做第3次改進。 這次我們的目前是把哪個動態(tài)部分抽象出來。
5. delegate, protocol
這個會列出來因為,我感覺問它的數(shù)量僅此于內(nèi)存管理部分,它們用得很頻繁,并且它們是多鐘設計模式的重要組成部分。
6. responder chain
7. Memory Reference Counting(RC) & Automatic Reference Counting(ARC)
這個也許是問得最多的問題了吧。所有這些問題往往來源于3個地方,1、不了解底層機制;2、沒有吃透規(guī)則; 3、不了解常用container的Reference Counting特性,或著說沒有下功夫去看對應文檔。
1. 底層機制
大家是否知道從舊時代的RC到ARC機制到底意味著什么呢? 為什么ARC從開發(fā)速度,到執(zhí)行速度和穩(wěn)定性都要優(yōu)于rc?
開發(fā)速度不言而喻,你少寫很多release代碼,甚至很少去操心這部分。
執(zhí)行速度呢?這個還要從runtime說起,還記得我在第2點說得一句話么:“Runtime is everything between your each function call.”
RC是一個古老的內(nèi)存管理哲學,誰分配誰釋放。通過counting來計數(shù)到底該資源有幾個使用者。道理很簡單,但是往往簡單的東西人卻會犯錯。從來沒有一個程序員可以充滿信心的說,我寫得代碼從來沒有過內(nèi)存泄露。這樣來看,我們就更需要讓程序可以自己處理這個管理機制,這就需要把這個機制放到runtime里。
所以RC->ARC就是把內(nèi)存管理部分從普通開發(fā)者的函數(shù)中移到了函數(shù)外的runtime中。因為runtime的開發(fā)原型簡單,邏輯層次更高,所以做這個開發(fā)和管理出錯的概率更小。實際上編譯器開發(fā)人員對這部分經(jīng)過無數(shù)次測試,所以可以說用arc幾乎不會出錯。另外由于編譯的額外優(yōu)化,使得這個部分比程序員自己寫得代碼要快速很多。而且對于一些通用的開發(fā)模式,例如autorelease對象,arc有更優(yōu)秀的算法保證autoreleasepool里的對象更少。
2. RC規(guī)則
首先說一下rc是什么,r-Reference參照,引用 c-counting計數(shù), rc就是引用計數(shù)。俗話說就是記錄使用者的數(shù)量。 例如現(xiàn)在我有一個房間空著,大家可以進去隨意使用,但是你進門前,需要給門口的計數(shù)牌子+1, 出門時候-1。 這時候這個門口的牌子就是該房間里的人數(shù)。一但這個牌子變?yōu)椋拔揖涂梢园逊块g關閉。
這個規(guī)則可以讓NSObject決定是不是要釋放內(nèi)存。當一個對象alloc時候,系統(tǒng)分配其一塊內(nèi)存并且object自動計數(shù)retainCount=1 這時候每當[object retain]一次retainCount+1(這里雖然簡寫也是rc不過是巧合或者當時開發(fā)人員故意選的retain這個詞吧)每次[object release]時候retainCount-1 當retainCount==0時候object就真正把這快內(nèi)存還給系統(tǒng)。
3. 常用container的Reference Counting特性
這個規(guī)則很簡單把。但是這塊確實讓新手最頭疼的地方。 問題出在,新手總想去驗證rc規(guī)則,又總是發(fā)現(xiàn)和自己的期望不符合。
無數(shù)次看到有人寫下如下句子
復制代碼
|
復制代碼
|
當然了,我也做過類似的動作,那種希望一切盡在掌握中的心態(tài)。但是你會看到其他人告訴這么做完全沒有意義。rc does not work this way. 也許這樣的暴力釋放會起作用,但是retainCount并不是用來做這個的。每個數(shù)字意味著有其它對象引用該資源,這樣的暴力釋放很容易導致程序崩潰。這個數(shù)字也許并不是你心目中的哪個。因為你很難跟蹤到底哪些對象引用的該資源。你用代碼建立的資源不光只有你的代碼才會用到,你調用的各種Framework,F(xiàn)ramework調用的Framework,都有可能改變這個資源的retainCount. 所以去驗證rc規(guī)則不是明智之舉。
你能做的就是理解規(guī)則,使用規(guī)則,讀文檔了解container的引用特性。或者干脆移到arc上面,讓runtime環(huán)境處理這些問題。
最后說一下不用arc的情況。目前情況來看,有不少第三方的庫并未支持arc,所以如果你的舊項目使用了這些庫,請檢查是否作者發(fā)布了新版本,或者你需要自己修正支持arc。
8. class heritage
9. English
10. Just trying to be smart
其實剩下這個有好幾點要說,但綜合一下把。思路有些相似
例如剛看到這個問題:
引用現(xiàn)在有A *a;A*b
[NSMutableArray addObject : a];
[NSMutableArray replaceObjectAtIndex:0 withObject:b]
執(zhí)行完這兩個之后,拿可變數(shù)組里面的0 的位置 就是b元素了,那這個時候a到哪里去了??是否還占用著內(nèi)存,如果占用內(nèi)存的話,又如何去釋放??
It's kind of silly. 我并不是想諷刺問問題的朋友。其實如果你真的了解了上面這些知識點,就不會再問這種問題的。 為什么不多思考一層呢,在問這個問題之前想想,到底為什么會問出這個問題? ”如果讓你給NSMutableArray實現(xiàn)一個replaceObjectAtIndex函數(shù)你會怎么寫?“ 難道連個[obj release]都考慮不到么?然后根據(jù)ARC,它到底釋放了沒不言自明了把。
其實這種問題論壇里很多的。不妨在迷惑的時候,先問問自己為什么會迷惑。
(1)這里其實很有意思,為何我用“更高層次思考”,而不是“更底層次”。作為一個編譯器和語言開發(fā)人員,面對的問題確實更底層沒錯,但是他們思考的維度更高,更抽象,這樣子。一個不算恰當?shù)谋确骄秃孟褚粋€三維世界的人處理二維世界的一條線的問題。 @import url(http://www.shnenglu.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
From: http://www.cocoachina.com/bbs/read.php?tid=74564