的主要問題,在我看來,是你設置你的局部變量nil
,然後你繼續嘗試使用這些本地像release
之類的方法中的變量,但因爲它們已被設置爲nil
,這些方法現在什麼也不做,而具有+1 retainCount
(或現在+2因爲您已將它們添加到視圖中)的對象永遠不會釋放。
因此,我建議如下:
//Here is pictures Data;
self.klpArry = self.pictureData;
CGSize size = self.klpScrollView1.frame.size;
for (int i=0; i < [klpArr count]; i++) {
UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake((size.width * i)+300, 20, 546, 546)];
NSString *filePath = [[NSBundle mainBundle] pathForResource:[klpArr objectAtIndex:i] ofType:@"jpg"];
UIImage *imageData = [[UIImage alloc]initWithData:[NSData dataWithContentsOfFile:filePath]];
[iv setImage:imageData];
iv.backgroundColor = [UIColor grayColor];
[self.klpScrollView1 addSubview:iv];
// Don't set these to nil, or else subsequent release statements do nothing!
// These statements are actually not necessary because they refer to local
// variables so you don't need to worry about dangling pointers. Make sure
// you're not confusing the purpose of setting a pointer to nil in ARC to
// what you're doing in your non-ARC code.
//
// imageData = nil;
// iv = nil;
// You don't want to set this to nil because if iv is not nil, your image
// will be removed from your imageview. So, not only is this not needed,
// but it's undesired.
//
// iv.image = nil;
// This statement is not necessary for the same reason you don't do it
// to imageData or iv, either. This is probably even worse, though, because
// filePath is not a variable that you initialized via alloc. You should
// only be releasing things you created with alloc (or new, copy, mutableCopy,
// for which you issued a retain statement).
//
// filePath = nil;
[imageData release];
// filePath is a +0 retainCount already, so don't release. You only release
// those items for which you increased retainCount (e.g. via new, copy,
// mutableCopy, or alloc or anything you manually retained).
//
// [filePath release];
[iv release];
}
// show the picture in scrollview;
[self.klpScrollView1 setContentSize:CGSizeMake(size.width * numImage, size.height)];
self.klpScrollView1.pagingEnabled = YES;
self.klpScrollView1.showsHorizontalScrollIndicator = NO;
self.klpScrollView1.backgroundColor = [UIColor grayColor];
因此,你的代碼將被簡化(和糾正),以可能只是:
//Here is pictures Data;
self.klpArry = self.pictureData;
CGSize size = self.klpScrollView1.frame.size;
for (int i=0; i < [klpArr count]; i++) {
UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake((size.width * i)+300, 20, 546, 546)];
NSString *filePath = [[NSBundle mainBundle] pathForResource:[klpArr objectAtIndex:i] ofType:@"jpg"];
UIImage *imageData = [[UIImage alloc] initWithData:[NSData dataWithContentsOfFile:filePath]];
[iv setImage:imageData];
iv.backgroundColor = [UIColor grayColor];
[self.klpScrollView1 addSubview:iv];
[imageData release];
[iv release];
}
// show the picture in scrollview;
[self.klpScrollView1 setContentSize:CGSizeMake(size.width * numImage, size.height)];
self.klpScrollView1.pagingEnabled = YES;
self.klpScrollView1.showsHorizontalScrollIndicator = NO;
self.klpScrollView1.backgroundColor = [UIColor grayColor];
或者你可以進一步簡化代碼通過使用autorelease
:
//Here is pictures Data;
self.klpArry = self.pictureData;
CGSize size = self.klpScrollView1.frame.size;
for (int i=0; i < [klpArr count]; i++) {
UIImageView *iv = [[[UIImageView alloc] initWithFrame:CGRectMake((size.width * i)+300, 20, 546, 546)] autorelease];
NSString *filePath = [[NSBundle mainBundle] pathForResource:[klpArr objectAtIndex:i] ofType:@"jpg"];
UIImage *imageData = [[[UIImage alloc] initWithData:[NSData dataWithContentsOfFile:filePath]] autorelease];
[iv setImage:imageData];
iv.backgroundColor = [UIColor grayColor];
[self.klpScrollView1 addSubview:iv];
}
// show the picture in scrollview;
[self.klpScrollView1 setContentSize:CGSizeMake(size.width * numImage, size.height)];
self.klpScrollView1.pagingEnabled = YES;
self.klpScrollView1.showsHorizontalScrollIndicator = NO;
self.klpScrollView1.backgroundColor = [UIColor grayColor];
順便說一句,語句(autorelease
):
UIImage *imageData = [[[UIImage alloc] initWithData:[NSData dataWithContentsOfFile:filePath]] autorelease];
也許可以簡化爲:
UIImage *imageData = [UIImage imageWithContentsOfFile:filePath];
這給你一個UIImage
,用+0 retainCount
(即你不需要release
它)從你的文件。
所以,一些結論性意見:
你真的應該大概檢討和研究的Advanced Memory Management Programming Guide。如果你對存儲器管理不熟悉,那麼讀起來很密集,但掌握這些概念(特別是在非ARC代碼中)是至關重要的。
如果你還沒有,我會鼓勵你通過靜態分析(「產品」 - 「分析」或轉變 + 命令 + 乙)來運行代碼。如果很多(如果不是大多數)這些問題不會被分析儀識別出來,我會很驚訝。通過分析器運行代碼時,您應該沒有任何警告。
如果你想把它提升到一個新的水平,你可能想對你的內存管理更加保守。治理原則將是一個系統設計,只加載在任何給定的時間在用戶界面上需要的圖像,這不僅涉及到calvinBhai對圖像延遲加載的出色建議(即,不會將圖像加載到內存中,直到您的UI 真的需要它們),但也是一個積極主動釋放圖像,一旦他們已經滾動屏幕。也許你不需要在你的應用中擔心它,因爲你一次只能處理20張圖片,但是如果你的任何投資組合/畫廊擴展到100或1000張圖片,那麼保留所有這些圖片的想法記憶在任何時候都是一個壞主意。這是一個更先進的概念,所以也許你應該首先關注現有代碼的基本內存管理問題,但是從更長遠的角度來看,您可能需要考慮延遲加載和主動釋放圖像。
我用[這種方法] [1]解決它,你可以看看。 [1]:http://stackoverflow.com/questions/10221591/how-to-optimize-uiscrollview-with-large-numbers-of-images/10274469#10274469 – Mil0R3
@Veelian謝謝你的評論,我看到這個代碼。有任何演示呢? – Allan