2012-04-06 51 views
0

我試圖在屏幕頂部向用戶下載多於600張圖像,並在屏幕上方顯示進度表。我使用淡入淡出層來屏蔽我的屏幕,以顯示活動和進度。下載大量圖像時發生內存泄漏問題

我收到之間的內存警告消息和應用程序崩潰。

我的步驟,以達到循環是:

  1. 在應用程序委託,我檢查第一核心數據錶針對其具有isImageAvailable布爾字段「0」值的所有行。
  2. 如果顯示我一些計數(比如說600),並且我用YES和NO選項顯示並提醒。
  3. 在是:[self performSelector:@selector(myDownload :) withObject:nil afterDelay:0.2];
  4. 在myDownload

    NSOperationQueue *queue = [NSOperationQueue new]; 
    // Create our NSInvocationOperation to call loadDataWithOperation, passing in nil 
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self 
                       selector:@selector(startUpdatingRecords:) object:nil]; 
    
    // Add the operation to the queue 
    [queue addOperation:operation]; 
    [operation release]; 
    [queue release]; 
    
  5. 在startUpdatingRecords:

    -(void)startUpdatingRecords:(id)sender 
    {  
    [self performSelectorInBackground:@selector(updateProgressMeter:) withObject: [NSString stringWithFormat:@"%d",self.loopStartIndex]]; 
    
    // Variable declarations    
    CGSize newSizeLarge ; 
    NSPredicate *predicate; 
    NSMutableArray *MatchingID; 
    Image_DB *data; 
    
    // Cache Directory path 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); 
    
    NSData *responseData; // = [[NSData alloc]init] ; 
    
    NSURL *url = [[[NSURL alloc]init] autorelease]; 
    NSMutableURLRequest *request = [[[NSMutableURLRequest alloc]init] autorelease]; 
    UIImage *imgSelected_Large = [[[UIImage alloc]init] autorelease]; 
    
    // Loop through all IDs 
    for (int i = 0; i < [self.arrayOfID count]; i++) //for (int i = loopStart; i < loopEnd; i++) 
    { 
    if (self.abortDownload) 
    {   
        break; 
    } 
    
    NSString *documentsDirectory = [[[NSString alloc] initWithFormat:@"%@",[paths objectAtIndex:0]] autorelease]; 
    documentsDirectory = [paths objectAtIndex:0]; 
    documentsDirectory = [documentsDirectory stringByAppendingFormat:@"/ImageFolder"]; // Image folder path 
    
    myClass *classObj = [self.arrayOfID objectAtIndex:i]; 
    
    NSString *strURl = [[[NSString alloc] initWithFormat:@"%@%@", self.MyURL,recipeObj.recipeImageStr] autorelease]; 
    //NSLog(@"URL = %@",strURl);   
    
    url = [NSURL URLWithString:strURl]; 
    request = [NSMutableURLRequest requestWithURL:url]; 
    responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:NULL error:NULL]; // Get Image Data into NSData 
    
    //imgSelected_Large = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:strURl]]]; 
    
    NSLog(@"Download Count = %d",i+1); 
    
    if (responseData != nil) 
    { 
        imgSelected_Large = [UIImage imageWithData:responseData]; 
    
        // Resizining image 
        newSizeLarge.width = 320;  
        newSizeLarge.height = 180;  
    
        imgSelected_Large = [self imageWithImage:imgSelected_Large scaledToSize:newSizeLarge]; // New sized image 
        NSData *dataPhoto; // no need to release it because UIImageJPEGRepresentation gives autoreleased NSData obj. 
        dataPhoto = UIImageJPEGRepresentation(imgSelected_Large, 0.6); // Set new image representation and its Compression Quality 
    
        documentsDirectory = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"Image_%d", classObj.nodeID]];    
        [dataPhoto writeToFile:documentsDirectory atomically:YES]; //Write file to local folder at default path 
    
        predicate = [NSPredicate predicateWithFormat: @"(image_ID = %d)",recipeObj.nodeID]; 
        MatchingID = [CoreDataAPIMethods searchObjectsInContext:@"Image_DB" :predicate :@"image_ID" :YES :self.managedObjectContext]; 
    
        // Setting flag variable for available image 
        for (int j = 0; j< [MatchingID count]; j++) 
        { 
         //Assign the Authors Records in Class Object and save to Database 
         data = (Image_DB*) [MatchingID objectAtIndex:j];     
         // data.image_large = dataPhoto; // Code for storing BLOB object to DB 
         data.extra_1 = @"1"; 
         //NSLog(@"Flag updated"); 
        } 
    } 
    // Exit out code 
    if (i == [self.arrayOfID count] - 1 || i == [self.arrayOfID count]) // Its the last record to be stored 
    {  
        NSError *error;    
        if (![self.managedObjectContext save:&error]) 
        { 
         // Handle the error... 
         NSLog(@"Error in updating %@",error); 
        } 
    
        self.isUpdateImageCalled = NO; 
        [self performSelectorOnMainThread:@selector(removeProgressMeter) withObject:nil waitUntilDone:NO]; 
    
    } 
    // Update UI screen while in downloading process 
    [self performSelectorInBackground:@selector(updateProgressMeter:) withObject:[NSString stringWithFormat:@"%d",self.loopStartIndex+i+1]]; 
    } 
    } 
    

如果我沒有釋放responseData然後我的應用程序顯示我記憶警告,並得到了墜毀。如果我發佈了,那麼[NSConcreteMutableData release]:發送消息發送到解除分配的實例0x1e931de0錯誤發生。

如何優化我的代碼。任何人都可以在我的代碼中建議我並重寫並製作精緻的代碼。

請幫我一把。

+0

願這個鏈接可以幫助你! http://stackoverflow.com/questions/3703734/downloading-large-amount-of-images-ipad-memory-leak – NSException 2012-04-06 07:42:32

回答

2

您的responseData返回sendSynchronousRequest是autoreleased因此你不應該自己釋放它。對於第一眼,我沒有看到代碼中的內存泄漏。有可能您的應用程序實際上使用太多內存,而不會泄漏它。嘗試把一個自動釋放池的內部進行循環:

for (...) { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    // your original code with a lot of autoreleased objects 

    [pool release]; 
} 

如果一個自動釋放池內包裝你的代碼,所有發送包裹內autorelease消息的所有對象將被真正發佈的時候池本身是發佈:這種方式可以在每個循環中清除內存。

另請參閱文檔中的Using Autorelease Pools,它特別提到您應該在「如果您編寫創建許多臨時對象的循環」的情況下使用它們。

+0

非常感謝,它爲我工作。再次感謝。 :) – 2012-04-06 08:33:42