2011-04-02 66 views
11

我發現在這個問題上的文檔不清楚:如果您有IBOutlet,但不是屬性,是否保留?

假設你正在使用iOS(不是Mac的情況下,不需要提及差異)。說它嚴格是4.0+(不需要提到舊操作系統的差異)。假設我們正在自動加載NIB。

假設你有一個UIViewController,BigView。假設NIB文件中有十幾個所謂的「頂級」項目......可以是自定義控件,圖像或其他任何東西。

假設您確定要在應用程序運行期間多次顯式創建並擺脫BigView。所以:

對於在NIB這些頂級項目之一,有三種可能性

(1)您沒有任何形式IBOutlet中的它,在所有。

(2)您確實有連接的IBOutlet - 但不是屬性。 (3)您確實有一個關聯的IBOutlet屬性(爲了避免混淆,我們會說一個retain屬性)。

那麼發佈BigView時該項目會發生什麼?

在(3)的情況下,您顯然必須明確釋放。如果你不這樣做,它會在視圖消失後停下來。沒問題。

在(1)的情況下,我認爲(但誰能真正確認?),當BigView消失的項目將被釋放。

在目前還不清楚會發生什麼(2)的情況下.......

在著名的參考鏈接展望:http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html這是非常可疑:

「在iOS中,nib加載代碼使用setValue:forKey:方法來重新連接每個插座。該方法類似地尋找適當的存取器方法,[因此,如果沒有其他人?告訴我們APPLE ...]回退在其他方式,當失敗... [GOOD GRIEF!]「

並檢查出這個文檔:http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html,向下滾動到「筆尖的對象保留」

所以......

「在筆尖文件對象與爲1的保留計數創建,然後自動釋放」神奇..

但等待!閱讀上幾句......

然而,...它使用現有的setter方法或默認保留的對象,如果沒有setter方法可用

他們在談論什麼?

他們是否意味着,如果沒有二傳手可用(伊娃,但無屬性),它是AGAIN未分配利潤(比「保留」之外,他們只提前款)---或者,他們是隻是重複自己,即「默認保留對象」與他們之前剛剛討論的「保留」相同(「保留計數爲1,然後自動釋放」)。

他們爲什麼會甚至提及自動釋放,如果這不是發生了什麼?

事實上 - 如果有人真的特別知道這個問題的答案...... 你怎麼知道?!?你問過DTS,還是通過測試,或者?我建議,關鍵文件(剛剛粘貼)是積極的不清楚。

再次 - 如果您有IBOutlet,,但不是屬性,連接到「頂級」對象。您是否負責釋放它?它保留了嗎?在那種情況下?

對於這個問題....只是在情況(1)是絕對的情況下,當BigView消失的啄將被釋放?我肯定會認爲是這樣,但誰知道呢?

的問題是,如果你使用一個IBOutlet實例變量會發生什麼,而不是一個屬性...

我傻傻從來沒有想過這個前/假設太多,沒有任何人有決定性的答案嗎?乾杯!!


爲了記錄我做了一個測試項目。

事實上(令我驚訝的是)僅僅將IB元件連接到IBOutlet的行爲顯然增加了一個保留

(我只能從僞劣實況認爲,在這種情況下你得到明確:保留,自動釋放,保留 - 導致一個權衡利弊保留)

所以,這就是答案。

我會發布演示項目。我也指示任何讀者約拿的答案,下面完美地解釋了setValue的行爲:forKey:乾杯

+0

非常感謝。我想知道完全相同的問題!閱讀蘋果文檔後,我感到非常困惑,所以我完全不確定要相信什麼。同時也感謝約拿對此的澄清。 – Buju 2012-01-24 15:30:26

+0

這是一個奇怪的 - 我同意你的觀點。因爲那個人給了我「超級權力」或這個網站上的東西,因此贊成投票!我是世界之王! – Fattie 2012-01-28 12:14:18

回答

11

我不明白是什麼原因導致這麼多的混亂,我認爲「筆尖的對象保留」文檔解釋究竟發生了什麼。我們來分解它,並且瀏覽所發生的事情:

創建的nib文件中的對象的保留計數爲1,然後自動釋放。

ClassLoadedFromNib *loadedObject = [[[ClassLoadedFromNib alloc] initWithCoder:coder] autorelease]; 

由於它重建對象分層結構,但是,UIKit中重新建立使用的setValue的對象之間的連接:forKey:方法,

[filesOwner setValue:loadedObject forKey:nameOfIBOutlet]; 

其中使用了ava的

如果沒有setter方法可用,則默認保留該對象。

-setValue:forKey: iOS中的默認行爲是大致

//lazy pseudocode 
if ([self respondsToSelector:@selector(@"setKeyName:")]) { 
    [self setKeyName:value]; 
} 
else { 
    object_setIvar(self, _keyName, [value retain]); 
} 

查看鍵值編程指南提供更多信息。除非您的文件的所有者對象覆蓋-setValue:forKey:(或+accessInstanceVariablesDirectly-setValue:forUndefinedKey:),否則需要按照上述方式管理對象所有權。


如果你定義筆尖文件對象網點,你應該總是定義訪問該出口處的setter方法(或聲明的屬性)。插座的設置方法應該保留它們的值,並且包含頂級對象的插座的setter方法必須保留它們的值以防止它們被釋放。

允許筆尖加載將伊娃直接設置到外部保留的對象是令人困惑的。不要這樣做。爲您的網點提供setter方法,以便加載對象的所有權清晰。


如果你不存儲在網點頂級對象,必須保留或者由loadNibNamed返回的數組:業主:options:方法或數組內的對象,以防止這些對象被過早釋放。

沒有連接到網點的物體已被自動發佈。保留它們或從-loadNibNamed:owner:options返回的數組如果您打算稍後嘗試訪問它們。

+0

Hey Joneh - 簡而言之,這是setValue:forKey:行爲的一個宏偉解釋,謝謝。 (在我詳細描述的情況下,doco有嚴重的缺陷......沒有你我們會被塞進。)乾杯! – Fattie 2011-04-03 20:26:50

2

這是一個有趣的問題,但由於文檔模糊不清,我認爲最好的計劃(和我相信推薦的蘋果)是要讓你的所有店鋪保留屬性。你確切知道在這種情況下會發生什麼,而且沒有什麼理由去做其他事情。

+0

我沒有dv,但是如果IB需要看到它,並且只有一個屬性(如果你想要getter/setters),那麼你只需要做出一些出路? – 2011-04-02 17:54:16

+0

如果你需要一個插座,這是因爲你計劃保持對從nib文件創建的東西的引用。使用屬性來管理該參考可避免上面提出的各種問題,並且還使內存管理更加容易。當然,你可以直接使用伊娃,但任何財產都是如此。也許你的意思是,當你打算使用除self之外的對象來改變相關值時,你可能只會使用一個屬性,但這正是從一個筆尖加載對象時發生的情況。 – Caleb 2011-04-02 18:27:08

+0

@Joe Blow,我認爲這是一個有趣的問題,但由於像這樣的話題容易讓初學者感到困惑,所以我想把最好的實用解決方案放在那裏。我知道我發佈的內容並不是你正在尋找的答案,如果有人爲此回答了這個問題,那很好。 – Caleb 2011-04-02 19:24:17

0

案例1)如果對象不被任何東西會在下次自動釋放池漏被釋放保留。

情況2)在上述你喬恩赫斯提到答案已經(用於文件的引用)用於這種情況下的Mac OS X和iOS之間的差異進行說明。

喬恩·赫斯正確或者是弗里曼是否正確?

在iOS情況下,赫斯和弗里曼都表示該對象將被保留。他們之間沒有矛盾。

它仍然強烈建議有setter方法對所有網點:

Resource Programming Guide, Nib Files

如果你定義筆尖文件 對象網點,你應該總是定義 setter方法(或聲明財產) 訪問該插座。二傳手 方法網點應保留 他們的價值觀......

+0

是的,它被保留下來,當你完成它時你應該釋放它(通常在'dealloc'中)。實際上我過去使用過這種方法,但現在我使用了這個屬性,因爲它對於我的代碼的未來維護者來說不會造成混淆。 – hoha 2011-04-02 15:58:15

+0

嗨Hoha。感謝您的指導。事實上,我做了一個測試項目,它證明了情況。我會發布它。我非常驚訝,僅僅將IB元素連接到IBOutlet的行爲實際上增加了一個保留。再次感謝和歡呼!對不起一些白癡投票你的評論! – Fattie 2011-04-02 18:59:52

相關問題