我正在尝试使用屏幕顶部的进度表向用户下载超过600个图像。我用一个淡化层屏蔽了我的屏幕以显示活动和进度。
我在中间收到内存警告消息,app崩溃了。
我到达循环的步骤是:
在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];
:
-(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 :(得分:2)
responseData
返回的sendSynchronousRequest
已自动释放,因此您不应自行释放。乍一看,我没有在代码中看到内存泄漏。您的应用程序实际上可能会使用太多内存,而不会泄漏内存。尝试在您的for循环中放置一个自动释放池:
for (...) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// your original code with a lot of autoreleased objects
[pool release];
}
如果您将代码包装在自动释放池中,发送的所有对象将在发布池本身时释放包含内的autorelease
消息:这样您就可以清除每个循环中的记忆。
另请参阅文档中的Using Autorelease Pools,它特别提到您应该在“编写创建许多临时对象的循环”的情况下使用它们。