2010-02-28 73 views
2

我正在開發一個iPhone應用程序,並且有關於內存管理的問題。 假設我有一個名爲Company的課程,其中NSNumber property(nonatomic,retain)被稱爲Id。 我這樣做:關於添加到數組的對象中保留計數的問題Obj-C

Company *company = [[Company alloc] initWithId:[NSNumber numberWithInt:1]]; 

Id現在應該有一個保留計數1? 然後我這樣做:

NSMutableArray *array = [[NSMutableArray alloc] init]; 
[array addObject:company]; 
[company release]; 

現在保留在Id上的數字是多少?還有1? 我應該在dealloc方法中加上Company我做[self.Id release]。 問題是,當我在我的應用程序中這樣做,然後嘗試訪問[[array objectAtIndex:0] Id]它超出了範圍。從我的角度來看,陣列保留了公司,因此我應該能夠通過陣列訪問Id。它是否正確?

編輯:忘了說,當我刪除Company[self.Id release]應用程序的工作,如果它的存在,它崩潰...

謝謝!

+0

你設置了NSZombieEnabled標誌嗎?這通常有助於縮小過度釋放問題。 – Abizern 2010-03-01 02:40:04

+0

我沒有。它是什麼以及如何使用它? – 2010-03-02 20:54:44

回答

2

至於你的具體問題:是的,這是正確的。該陣列保留添加到其中的任何對象,並且Company實例應保留Id對象。 (另外:該屬性應該命名爲id,而不是Id,以遵循Cocoa約定。)這假設您保留initWithId:方法中的值(使用self.Id[Id retain])。

我看不出你的代碼有什麼問題。我認爲這個錯誤一定是因爲你在將Company對象添加到數組並嘗試再次訪問它之間所做的事情。您是否在將[self.Id release];行添加到dealloc後發生錯誤?這也會很奇怪。

這聽起來像是你過度發佈了Company對象,或者陣列本身已經發布。你可以試着製作一個產生錯誤的小代碼例子(而不是隻是說「稍後我會這樣做......」)?

更普遍的答案是,你不應該考慮確切的保留數可能是多少。由於Cocoa的內部運作,保留數通常會高於您的預期。你應該記住的僅僅是哪些類擁有對象的所有權(例如NSArrayNSMutableArray),以及在哪些情況下你自己的代碼應該/不應該擁有對象的所有權。所以當你問保留計數是否仍然是1時,這稍微有點不合適。問題是任何對象是否仍然具有所討論對象的所有權。

+1

或者''myIdMember = [myIdArgument retain]'在'initWithId:'中。 – Dirk 2010-02-28 20:37:14

+0

感謝您的徹底解答! 是的,如果我從dealloc中刪除[self.Id release],應用程序按預期工作 - 感覺很奇怪。 我發佈的代碼是我真正做的簡化。 但是,正如所說,因爲當我刪除[self.Id發佈]時,所有東西都能正常工作,所以我可以得出結論:我過度發佈Id,而我根本不需要在公司類中完成它。不要修理沒有被破壞的東西嗎? =) – 2010-02-28 21:10:14

+1

我不相信你可以將變量/屬性命名爲「id」 - 這是一種類型! – 2010-02-28 21:12:11

3

首先,不要考慮保留計數的具體數字。認爲保留爲三角洲;您只增加或減少保留計數。

爲了回答您的具體問題:

會是什麼保留的ID數是 現在呢?還有1?我應該在 公司的dealloc方法中加上 [self.Id release]。問題是,當我在我的應用程序中這樣做,然後嘗試 訪問[[array objectAtIndex:0] Id] 它超出了範圍。從我的觀點 查看陣列保留公司和 因此,我應該能夠訪問 ID「通過」陣列。這是 是否正確?

Id的保留數是一個實現細節; NSNumber緩存一小部分值,因此,如果您考慮以絕對值計算保留計數,則保留計數可能與您可能期望的任何內容完全無關。

如果在平衡所有保留版本之後嘗試訪問對象,則說明您沒有正確執行內存管理指南。

假設你的「公司」實例保留了NSNumber的實例,那麼,是的,它應該仍然是可行的。 「超出範圍」是什麼意思?你有運行時錯誤還是編譯錯誤?發佈它,如果你這樣做。