2012-09-11 115 views
2

在我的應用程序中,我使用UIImageViewUIScrollView來顯示大量圖像(每次大約20張圖像,每張圖像大約600px * 500px,大小約600kb)。UIImageView和UIScrollView加載大量圖片

我使用此代碼來完成這個功能:

// 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 = nil; 
    iv = nil; 
    iv.image = nil; 
    filePath = nil; 
    [imageData release]; 
    [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]; 

但每次我初始化此功能時,內存將增加約5MB。其實我發佈了UIImageView,UIimageUIScrollViewvi.image=nil, [vi release])但它不起作用,分配的內存沒有被釋放。順便說一句,我用我的朋友的代碼第一vi.image = nil然後vi = nil;但圖片不會顯示在滾動視圖上。

+0

我用[這種方法] [1]解決它,你可以看看。 [1]:http://stackoverflow.com/questions/10221591/how-to-optimize-uiscrollview-with-large-numbers-of-images/10274469#10274469 – Mil0R3

+0

@Veelian謝謝你的評論,我看到這個代碼。有任何演示呢? – Allan

回答

3

的主要問題,在我看來,是你設置你的局部變量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它)從你的文件。

所以,一些結論性意見:

  1. 你真的應該大概檢討和研究的Advanced Memory Management Programming Guide。如果你對存儲器管理不熟悉,那麼讀起來很密集,但掌握這些概念(特別是在非ARC代碼中)是至關重要的。

  2. 如果你還沒有,我會鼓勵你通過靜態分析(「產品」 - 「分析」或轉變 + 命令 + )來運行代碼。如果很多(如果不是大多數)這些問題不會被分析儀識別出來,我會很驚訝。通過分析器運行代碼時,您應該沒有任何警告。

  3. 如果你想把它提升到一個新的水平,你可能想對你的內存管理更加保守。治理原則將是一個系統設計,只加載在任何給定的時間在用戶界面上需要的圖像,這不僅涉及到calvinBhai對圖像延遲加載的出色建議(即,不會將圖像加載到內存中,直到您的UI 真的需要它們),但也是一個積極主動釋放圖像,一旦他們已經滾動屏幕。也許你不需要在你的應用中擔心它,因爲你一次只能處理20張圖片,但是如果你的任何投資組合/畫廊擴展到100或1000張圖片,那麼保留所有這些圖片的想法記憶在任何時候都是一個壞主意。這是一個更先進的概念,所以也許你應該首先關注現有代碼的基本內存管理問題,但是從更長遠的角度來看,您可能需要考慮延遲加載和主動釋放圖像。

+1

+1很好的解釋。爲了擴展數字3,查看平鋪的滾動視圖,在這裏你可以重用滾動視圖的各個部分,就像'UITableView'重用它的單元格一樣。 –

+0

@Rob謝謝你的評論,我會認真閱讀文章。 – Allan

2

如果內存是你的關心,

嘗試延遲加載圖像=負載可見圖像,下一個和以前的形象。您不必將所有圖像添加到您的klpscrollview。

一旦你找出延遲加載到你的滾動視圖的圖像,那麼你可以考慮修復不顯示在你的滾動視圖上的圖像。

更容易

將搜索「延遲加載的UIImage的UIScrollView」

+0

謝謝你的回答,我會搜索它。但任何想法解決我的問題? – Allan