2011-07-25 42 views
2

好吧,如果我沒有分配任何對象而編寫了很多代碼,內存在哪裏?如何用圖像管理內存

例如,而不是

UIImage *myImage = [UIImage imageNamed:@"image.png"]; 
imageView.image = myImage; 
[myImage release]; 

imageView.image = [UIImage imageNamed:@"image.png"]; 

在所有我的代碼。我沒有看到第二個例子中的內存情況。我仍然在學習,並在整個應用程序中使用第二個示例編寫了很多代碼,而沒有分配任何對象。它在模擬器中總是運行良好,但實際的設備無法處理內存和崩潰。所有關於內存管理的教程都是從釋放你創建的對象的角度來談論它,但是因爲我從來沒有創建任何對象,所以我被卡住了。

回答

4
UIImage *myImage = [UIImage imageNamed:@"image.png"]; 
imageView.image = myImage; 
[myImage release]; 

你做了一個雙發佈。 [UIImage imageNamed]是autoreleased,所以你不需要明確地釋放對象。您的應用程序可能因雙重版本而崩潰,而不是因爲未發佈的對象。

閱讀拇指的簡單規則,release/autorelease confusion in cocoa for iphone

規則很簡單:如果你的Alloc,複製或保留,這是你的責任 釋放。如果你沒有,那不是。但是,如果你需要依賴一個物體呆在附近,你必須保留(和 後來的版本)。


更多的例子:

imageView.image = [UIImage imageNamed:@"image.png"]; 

上面的代碼是有效的,你不必將其釋放。但是,如果你使用了大量的直接分配未發佈對象,如這一個:

foo.bar = [[SomeClass alloc] initWithSomething:@"Init"]; 

您只需輕鬆地通過增加自動釋放修復:

foo.bar = [[SomeClass alloc] initWithSomething:@"Init"] autorelease]; 

或者,如果你想要的長,但可以說是更合適方式(因爲你控制對象被釋放時):

SomeClass *tempVar = [[SomeClass alloc] initWithSomething:@"Init"]; 
foo.bar = tempVar; 
[tempVar release]; 
1

你混淆聲明變量與分配內存/對象。在上述兩種情況下,你的代碼的重要組成部分,實際上是這樣的:

[UIImage imageNamed:@"image.png"]; 

此代碼恰好調用上,做了一些事情的UIImage類方法。其中之一是UIImage對象的分配和初始化。在你的第一個例子中,你將這個分配的對象存儲到一個名爲myImage的變量中。然後,您將閃亮的新對象移動到另一個(類)變量「imageView.image」中。

UIImage *myImage = ... 

在你給你還在存儲該分配對象中的變量,所不同的是在此情況下,你跳過中間分配和存儲對象直接進入類變量imageView.image的第二示例。

imageView.image = [UIImage imageNamed:@"image.png"]; 

想想變量與對象的一種方法是將它們與房屋進行比較。在這種情況下,變量是你的地址,而對象是你的房子。有幾個人可以有你的地址,但無論他們有多少人,當他們選擇訪問時,他們都會去同一棟房子。因此,在您的示例中,myImageimageView.image是指向同一房屋或對象的地址,即UIImage的一個實例。在你的例子中,除非你將它用於其他目的,否則實際上並不需要創建中間變量。

至於碰撞,你應該閱讀Apple's memory management guide。這可能需要一段時間,但您會習慣Apple在保留和釋放對象方面遵循的標準。請注意,XCode 4.2 中的新自動參考計數緩解了這些問題,但它也有其自己的學習曲線。但總而言之,因爲你釋放了一個你不擁有的對象,所以你正在崩潰。 UIImage上的類方法imageNamed返回該類的自動釋放實例。您不需要在代碼中發送另一個版本,這就是程序崩潰的可能來源。

2
imageView.image = [UIImage imageNamed:@"image.png"]; 

這條線很棒,正確。

imageNamed:方法的實施

,其可以返回之前新UIImage分配內存,實例化新的UIImage成存儲器,然後autorelease它。 autorelease池在你的代碼運行後消失,如果沒有保留它,則釋放圖像對象。

那麼「內存在哪裏?」。它將進入自動釋放池。但真的,除非你打電話alloccopy...retain你不必關心。

正如Manny所說,您的第一個片段確實會超出發佈範圍並且不正確。