0

我使用[self retain]來保存一個對象本身,[self release]將它釋放到別處。有時候這很方便。但這實際上是一個參考循環或死鎖,大多數垃圾收集系統都要解決這個問題。我不知道是否objective-c的autorelease池可能會找到循環,並通過在達到[自釋放]之前釋放對象來給我帶來驚喜。我的方式是否鼓勵?我怎樣才能確保垃圾收集,如果有的話,不會太聰明?我可以使用[self retain]將對象本身保存在objective-c中嗎?

+1

你可能想要避免這種模式,除了一些非常特殊的情況。您能否詳細介紹一下您的使用情況?爲什麼一個對象會自我保留,當它的分配必須從其他地方完成時? – Doodloo 2011-03-23 03:04:29

+0

上下文是,我使用UIViewController的子類作爲全屏模型對話框。父視圖發出對話框,但是當對話框關閉時,它確實需要知道事件。 – willzeng 2011-03-23 08:45:28

+0

上下文是,我使用UIViewController的子類作爲全屏模型對話框。父視圖發出對話框,但是當對話框關閉時,它確實需要知道事件。如果我直接使用UIView而不是UIViewController,那麼自從[self removeFromSupperView]時,視圖的引用計數減少一個,就沒有這個問題了。但是,UIViewController的子類可以自動鏈接到一個同名的xib文件,這就是爲什麼我使用UIViewController。 – willzeng 2011-03-23 08:55:32

回答

3

這種工作方式非常令人沮喪。看起來你需要一些關於內存管理的指針。

從理論上講,物體應該存在,只要它有用。有用的對象很容易被發現:它們被直接引用到線程堆棧的某個地方,或者如果您製作了所有對象的圖形,則可以通過鏈接到線程堆棧上引用的某個對象的某個路徑進行訪問。那些沒有被引用的「自己」生活的對象是沒有用的,因爲沒有線程可以觸及它們來讓它們執行某些事情。

這是垃圾收集器的工作原理:它遍歷對象圖並收集每個未引用的對象。請注意,Objective-C並不總是垃圾收集,因此必須建立一些規則。這些是memory management guidelines for Cocoa

簡而言之,它基於「所有權」的概念。當您查看對象的引用計數時,您會立即知道有多少其他對象依賴於它。如果一個對象的引用計數爲3,這意味着另外三個對象需要它正常工作(因此它具有它)。每次你保留一個對象的引用(除了在極少數情況下),你應該調用它的方法retain。在你放棄參考之前,你應該調用它的release方法。

還有一些重要的創建對象的規則。當您撥打alloccopymutableCopy時,您獲得的對象已有一個refcount爲1.在這種情況下,它意味着調用代碼負責在不需要時釋放該對象。當你返回對象的引用時,這可能會有問題:一旦你返回對象,理論上你不再需要它,但是如果你打電話給release,它就會立即被銷燬!這是NSAutoreleasePool對象有通過調用對象的autorelease,你放棄它所有權(如如果你叫release),除了參考不立即撤銷。相反,它被轉移到NSAutoreleasePool,即一旦它收到release消息本身就會釋放它。 (無論何時你的代碼被Cocoa框架回調,你都可以確定自動釋放池已經存在。)

這也意味着如果您沒有在其上呼叫alloccopymutableCopy,換句話說,如果您另外獲得對這樣的對象的引用,則不需要在其上調用release。如果您需要像往常一樣圍繞這樣的對象,請撥打retain,然後在release完成後再撥打電話。

現在,如果我們試圖將這個邏輯應用到您的用例中,它就顯得很古怪。一個對象不能在邏輯上擁有自己,因爲這意味着它可以存在,在內存中是獨立的,不會被線程引用。顯然,如果您有機會自己致電release,這意味着您的某個方法正在執行;因此,你應該有一個參考,所以你不應該首先需要retain。我無法用您提供的一些細節來說,但您可能需要查看NSAutoreleasePool對象。

+0

感謝您的詳細信息。我在C++中做了一些垃圾收集工作,所以我知道它是如何工作的基礎知識,比如通過從堆棧或全局對象開始維護依賴關係和查找引用關閉。這就是爲什麼我不知道objective-c是否也會這樣做的原因。我沒有給出問題的上下文,所以我在這裏添加它:我使用UIViewController的子類作爲對話框。當一個對話框關閉時,它只是調用[self.view removeFromSuperView],並且在大多數情況下不需要通知其擁有者。 UIViewController必須找到一種方法來釋放它自己。如果objective-c被很好地垃圾回收 – willzeng 2011-03-23 09:10:00

+0

...如果objective-c很好地被垃圾回收,self.view也應該維護一個ref(self)(UIViewController),並且在調用[self.view removeFromSuperView]之前,引用閉包有外部引用(超級視圖),並且不會被釋放。但是在調用[self.view removeFromSuperView]後,引用循環(self&self.view)變成死鎖,因此可以通過垃圾回收系統查找和釋放。 Objective-c的垃圾回收似乎是半自動的,並沒有以這種方式實現,這讓我認爲這意味着自我保留被鼓勵嗎?我知道應該總是儘量避免 – willzeng 2011-03-23 09:22:14

+0

我知道一個人應該總是儘量避免這種情況,但是當使用遺留代碼(如UIViewController)時,如果我可以這樣說,如何平衡便利性和完整性? – willzeng 2011-03-23 09:26:12

1

如果您使用保留/釋放內存模型,它應該不成問題。沒有什麼會去尋找你的[self retain]並顛覆它。但是,如果您切換到使用垃圾收集,其中-retain和-release是空操作,情況可能並非如此。

Here's another thread on SO on the same topic.

我想重申,包括短語回答「ickyness壓倒性的感覺。」這不是非法的,但除非有很強的理由,否則這感覺就像是一個糟糕的計劃。如果沒有其他的東西,它似乎是偷偷摸摸的,這在代碼中從來都不好。請注意該線程中的警告,以使用-autorelease而不是-release。

相關問題