2011-11-01 47 views
6

在代碼,我繼承,我已經看到了以下內容:爲IBOutlet Work的只讀屬性是否會更好?

@property (readonly) IBOutlet UIImageView * bgImage; 

當我想到一個保留的內存模型,如:

@property (readonly, retain) IBOutlet UIImageView * bgImage; 

我很困惑,爲什麼第一屬性定義工作不會造成問題。

此外,還有在一個dealloc中作爲release你所期望的一樣:

-(void)dealloc 
{ 
    [_bgImage release]; 
    [super dealloc]; 
} 

我會很感激,如果有人能想出這種解釋。我已經和最初的開發者談過了,他正在嘗試寫出更簡潔的代碼,這就是爲什麼他在內存模型中忽略了retain(似乎不必要)。

我不知道是否IBOutlet基本上對待像伊娃IBOutlet聲明,因爲它是隻讀的(沒有設置使用,因此默認分配內存模型沒有區別)。

如果IBOutlet中從未預期發生變化,會使用一個只讀屬性,無記憶模式實際上是定義性的最好方法是什麼?

回答

7

iOS上的筆尖加載器會在筆尖的對象,然後自動釋放他們。當它建立連接到網點時,它使用setValue:forKey:,它將調用該密鑰的setter方法。如果沒有設定器被定義,諸如當IBOutletreadonly屬性,所述對象被分配之前保留反正。 (這是Managing Nib Objects in iOS資源編程指南中的意譯。)

所以在實際事實上,插座是否被聲明爲retainassign與出口的對象所擁有的另一端對象。它可以通過setter方法保留,也可以在沒有找到setter時被setValue:forKey:保留。由於在第二種情況下沒有其他可能的所有者,因此您可以認爲帶有插座的對象是所有者。因此,筆尖中的物體應該在dealloc中釋放。

我同意你應該通過改變屬性屬性來包括retain這個內存條件。*是否它是readonly似乎沒有什麼區別(但是,見下文)。從概念上講,是的,該對象是隻讀的,因此是否明確標記它取決於您是否認爲這是一個IBOutlet這一事實適當記錄。

更新:下面 Paul.s的評論促使我做一個快速測試。我創建了一個UIView子類,它記錄了它的alloc,retain,,releaseautorelease調用,將它的一個實例粘貼到筆尖中,並通過屬性給應用程序委託人IBOutlet

當手動計算參考計數活動時,當物業爲(readwrite, assign)時,實例出現淨0計數。當物業被宣佈爲推薦方式時,它是淨+1,(readwrite, retain)也是,當時是(readonly, assign)。所有這些都非常符合預期 - 當它是(readwrite, assign)時,分配設置器用於建立連接,並且不進行保留。當它是readonly時,連接機制退回到自己的保留狀態。

最有趣的是,當我試圖改變這一觀點與物業的背景色崩潰的應用程序中聲明(readwrite, assign)(即,當它可能已釋放),我看到了retain彈出一個最後一次通話。

我想這是歸結爲:遵循蘋果的建議 - 他們知道幕後發生了什麼,並且(禁止錯誤)不會誤導你。

(另外一件事情就是,一如既往地擔心絕對引用計數並不會非常有用 - 計數一直達到6,一次就超過了二十次調用到retainrelease - 你只需要擔心的保留和您直接導致發行)


*當然,這ARC下改變。我解釋的信息在本章的「遺留模式」部分。在ARC下,建議IBOutlets的值爲weak,除非它們是頂層的,在這種情況下,它們應該是strong。這樣做意味着您依靠視圖層次結構(保留其子視圖的視圖)來維護自己。

+0

'這個出口是否被聲明爲保留或分配,另一端的對象是否被帶有出口的對象所擁有(這不是很清楚),只有當它被設置爲'readonly'時才這樣嗎?如果它是'(分配,讀寫)'那麼肯定會使用非保留的setter,並且不會保留'' - 我只提到,因爲它是你答案的唯一部分,這有點含糊 –

+0

我認爲是......這似乎是它所說的。 –

+2

@ Paul.s:看到我的更新 - 我決定手工計算參考活動,結果是,我認爲,有啓發性。 –

2

我已經報告了一個蘋果的錯誤,如果你創建IBOutlet實例變量而不是屬性,那Xcode仍然會自動在dealloc等中創建發行版。iOS應用程序的Xcode似乎總是爲IBOutlet創建版本,無論它是否正確。

人員我不喜歡屬性IBOutlet,因爲它意味着您將它們聲明爲readwrite,這意味着它們被記錄爲readwrite,但大多數情況下(幾乎總是),IBOutlet在概念上應該是隻讀的。顯然,他們必須先讀寫才能設置。

+0

您可以在公共接口中聲明'@property(nonatomic,只讀)'並在類擴展中聲明'@property(nonatomic)IBOutlet'。 –