
iOS的記憶體管理真的不少東西要學,在Objective-C裡有時候會看到一些程式碼這樣寫:
1 2 3 4 5 6 7 | |
先把它release掉了,然後下一行再把它指向nil。nil跟其它程式語言裡的null或none是一樣的東西,就是nothing、虛無飄渺、沒有任何東西的意思。
問題是,這個nil是必要的嗎? 不指向nil會出什麼包嗎?
先來釐清一個觀念:對一個物件發送release訊息並不會直接把物件佔用的記憶體還給記憶體,release這個動作只是減少retain count而已,當retain count變成0的時候會自動啟動dealloc,這時候才是真正的被消滅掉。
在Objective-C裡所有的物件變數都是指標,指向某一塊配置的記憶體,所以,下面這行程式碼:
1
| |
意思是把mybook這個變數指向nil。這樣說來,是不是也不用什麼release了,直接把變數設定成nil不就好了?
我們先來看個例子:
1
| |
這應該不陌生了,這建立一個名為img的指標變數,並指向某一個UIImage的實體。如果我在它下面再加一行:
1
| |
就是再做一次alloc/init,讓剛剛那個img變數指向這個新的實體。看起來很直覺,但指標的東西跟我們一般寫的程式的習慣不同,當你把img指向另一個新的實體,原來舊的實體並不會消失,它會存在記憶體裡,只是沒有人指向它,所以也沒有人能再存取它。當然在有支援GC的環境上,系統會自動回收那些沒人要的東西,但在不支援GC的環境,那個沒人要的孩子就會一個人孤獨的漂流著了,所以如果你要這樣做,請記得先把原來的那顆給release掉,再給它一顆新的。
那如果我再接著這樣做:
1
| |
把img指向nil並不會減少retain count,那剛剛前面我產生的第二個物件就會跟第一個物件一樣,它不會消失,它只是在記憶體空間裡漂流,當然它佔用的記憶體也不會還給系統。所以請切記,如果你要把物件給丟掉,不要直接把變數設成nil,請使用release或autorelease。
回到最一開始的問題,我的答案是:其實是沒什麼需要一定要在release之後再弄個nil給它,但這樣做是個好習慣。
那什麼時候會出問題?
在別的程式語言裡,當你要存取null物件的時候,通常會直接跳錯誤給你看,但在Objective-C裡如果你對nil送訊息的,即使是沒定義的method,它也只會靜靜的不回應而已。所以,回到最前面的程式碼來看,當你把mybook給release之後,也許有那個萬一的情況下,有別的method要存取它,但它可能因為已經被dealloc掉了,所以就會爆炸了(發生機會很小,但不代表永遠不會發生)。但如果把mybook指向nil,即使有人要再來存取這個mybook也不會出現錯誤了。
以上,我對記憶體管理的東西的了解相當有限,所以如果以上內容有誤還請不吝指正 :)