2010-11-27 90 views
0

我的應用程序按特定順序從URL下載圖像,然後用戶查看它們。我有應用程序預先載入下一張圖像,並將舊圖像保存在緩存中。內存未被正確釋放?

此緩存基本上是一個NSMutableDictionary,其中的鍵與圖像ID相關聯。緩存中的每個對象也是一個帶有url,圖像URL,標題和NSData對象的NSDictionary。當我下載圖片時,我用這些元素將一個新的字典對象添加到緩存中。我像這樣存儲NSData對象:NSData * imgData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imageurl]];然後我將這個對象添加到子字典對象。

大量的照片存儲和緩存後,這顯然佔用大量的RAM,所以我通過清除整個緩存來響應內存警告。問題是,無論我嘗試過什麼,都不會釋放RAM。物體消失(像他們應該),但不要退回RAM。我曾嘗試執行以下操作:

  • 通過緩存詞典循環,釋放在孩子字典中的數據對象,那麼當所有項目都通過循環,清除所有緩存字典子對象。
  • 通過緩存詞典循環,釋放孩子的字典,完成後刪除所有對象
  • 即使在拆除所有對象,然後釋放整個緩存對象(然後重新創建它,因爲它仍然需要使用)
  • 而釋放,刪除等

問題的其他隨機連擊是什麼,我都試過了釋放RAM。有沒有我做錯了釋放NSData對象的內存?

+0

當您下載數據時,您使用什麼樣的緩存策略?您是否確認(即泄漏或分配)記憶確實正在泄漏或放棄? – 2010-11-27 08:16:36

回答

1

內存管理在Objective-C中的工作方式是通過alloc/initing,--retaining或-copying獲得對象的所有權,當您不再需要它時,通過-release或-autorelease取消它。

你想要做的是:

1)創建的數據對象

NSData *imgData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imageurl]]; 

您現在擁有該對象imgData點。

2)對象添加到您的孩子的字典

[childDictionary setObject:imgData forKey:@"imgData"]; 

3)駁回數據對象。你不再需要它了。 childDictionary需要它,但那不是你的問題。 childDictionary和其他所有對象一樣,負責管理自己的內存和所有權。

[imgData release]; 

另一種方法是創建數據對象的自動發佈版本,並將其添加到dictioary中。

接下來,您需要確保您正確管理childDictionary的內存以及cache的內存。例如:

1)創建一個自動釋放childDictionary

NSMutableDictionary *childDictionary = [NSMutableDictionary dictionary]; 

2)添加的東西childDictionary(像我們以前那樣)

3)添加childDictionary到緩存

[cache setObject:childDictionary forKey:yourKey]; 

4)由於childDictionary是自動發佈的,所以你不需要(也不應該)釋放它,現在你不需要它。它將在稍後由主自動釋放池自動釋放。如果你創造了使用childDictionary:

NSMutableDictionary *childDictionary = [[NSMutableDictionary alloc] init]; 

返回爲1的retainCount一個對象,那麼你會需要現在就解僱所有權:

[childDictionary release]; 

至於緩存的話,你可能想要長期保持這種狀態:它很可能是任何對象管理緩存的實例變量,並且當您點擊內存警告時,它會用[cache removeAllObjects]重置。

如果你在Mac上使用垃圾收集進行開發,所有這些都是沒用的。但是,既然你在打電話,你需要知道這些關於內存管理的簡單規則。我的解釋確實忽略了許多您應該熟悉的概念,所以我強烈建議您閱讀the Apple documentation about this

0

演示此泄漏的簡化代碼示例會很有幫助。僅僅從你的描述來看,你用來將imgData添加到字典的調用是否可以保留它?如果你沒有立即在你自己的代碼中發佈imgData,你的保留計數就是2.當你的本地imgData指針超出範圍時,你將泄漏內存。不過,這只是在沒有代碼示例的情況下在黑暗中刺中。