Core Data - memory usage: my application crashes

My question is about basic data and memory usage. I used to use basic data, but this time the amount of data is higher, and this made me realize that there was much more to know. I saw that there are several other similar messages, and I have interesting information from them, but after applying it, my applications still fail. I have been dealing with this issue for a week now. Someone please help.

In principle, I have three subsequent similar cycles of 64, 15 and 17 iterations, respectively. They work great on a simulator. Tested on a pair of iPads, they receive memory alerts, and they crash at the same iteration (number 34 of the first loop). After testing the iPad 2, it will work at number 14 of the second cycle. The tools show memory usage of about 1.5 MB both in real time and in general. There are leaks for a few kilobytes.

Loops do the following (code below)

  • Fetch with kernel data
  • For each record, take a parameter stored as an attribute of a string property (String)
  • Call a procedure that takes this parameter and which returns data (about a hundred KB)
  • Save this data in another property attribute (Transformable) of the same row

Pretty common task isn't it?

Now that I have problems with memory, I tried to use all the tools I know that:

  • release owned asap objects
  • create autodetection pools and merge them as soon as possible for objects that do not belong to them
  • keep context as soon as possible
  • turn objects into errors as soon as possible

After applying all these methods, I got an exciting result: the application crashes at the same point as before.

Here is the code.

- (void) myMainProcedure { [self performLoop1]; [self performLoop2]; // Similar to loop1 [self performLoop3]; // Similar to loop1 } - (void) performLoop1 { NSError * error = nil; NSAutoreleasePool * myOuterPool; NSAutoreleasePool * myInnerPool; NSManagedObjectContext * applicationContext = [[[UIApplication sharedApplication] delegate] managedObjectContext]; [applicationContext setUndoManager:nil]; NSEntityDescription * myEntityDescription = [NSEntityDescription entityForName:@"EntityName" inManagedObjectContext:applicationContext]; NSFetchRequest * myFetchRequest = [[NSFetchRequest alloc] init]; [myFetchRequest setEntity:myEntityDescription]; NSString * column = @"columnName"; NSPredicate * aWhereClause = [NSPredicate predicateWithFormat: @"(%K = %@)", column, [NSNumber numberWithInt:0]]; [myFetchRequest setPredicate: aWhereClause]; myOuterPool = [[NSAutoreleasePool alloc] init]; NSArray * myRowsArray = [applicationContext executeFetchRequest:myFetchRequest error:&error]; NSMutableArray * myRowsMutableArray = [[NSMutableArray alloc] initWithCapacity:0]; [myRowsMutableArray addObjectsFromArray: myRowsArray]; [myOuterPool drain]; [myFetchRequest release]; EntityName * myEntityRow; int totalNumberOfRows = [myRowsMutableArray count]; myOuterPool = [[NSAutoreleasePool alloc] init]; for (int i = 0; i < totalNumberOfRows; i++) { myInnerPool = [[NSAutoreleasePool alloc] init]; myEntityRow = [myRowsMutableArray objectAtIndex:0]; NSString * storedSmallAttribute = myEntityRow.smallAttribute; UIImageView * largeData = [self myMethodUsingParameter: smallAttribute]; myEntityRow.largeAttribute = largeData; [myRowsMutableArray removeObjectAtIndex:0]; [applicationContext save:&error]; [applicationContext refreshObject:myEntityRow mergeChanges:NO]; [myInnerPool drain]; [largeData release]; } [myOuterPool drain]; [myRowsMutableArray release]; } - (UIImageView *) myMethodUsingParameter : (NSString *) link { UIImageView * toBeReturned = nil; NSURL *pdfURL = [NSURL fileURLWithPath:link]; CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfURL); CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1); CGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox); UIGraphicsBeginImageContext(pageRect.size); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetRGBFillColor(context, 1.0,1.0,1.0,1.0); CGContextFillRect(context,pageRect); CGContextSaveGState(context); CGContextTranslateCTM(context, 0.0, pageRect.size.height); CGContextScaleCTM(context, 1, - 1); CGContextSetInterpolationQuality(context, kCGInterpolationHigh); CGContextSetRenderingIntent(context, kCGRenderingIntentDefault); CGContextDrawPDFPage(context, page); CGContextRestoreGState(context); UIImage *imageToBeReturned = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); CFRelease(pdf); toBeReturned = [[UIImageView alloc] initWithImage:imageToBeReturned]; UIGraphicsEndImageContext(); return toBeReturned; } 
  • note that

    • A volatile array was introduced as a (apparently useless) strategy for eating objects released earlier
    • An ad part of the same strategy has been added to pools.
    • The statement about the quality of interpolation was the only one who could improve the situation (say, to move the accident) a little forward).
    • Keeping the counter for managed objects within a cycle of 6 to 10 (?) I know that rc is not valuable but still, I did a test and I found out that I can send messages with several versions of objects before forcing the application to crash for of this. But the fact is that I should not release an object that I do not have, right? ....
    • The entity on which the request is set also has some bi-directional relationships with other entities, but is it still meaningful?

Thanks.

+4
source share
1 answer

I think you should take a fresh look at your problem. There are many ways to handle Core Data, which are much simpler than your approach. Creating class files for your Core Data objects can help you. In addition, when you save your files, you should seriously evaluate the need for each object and whether it is better to do it. In your case, I would suggest two sentences:


For each pdf url

  • a Enter a unique identifier.
  • b. Store this unique identifier in your data warehouse.
  • c. Add the queue URL to the background process that creates your PDF file (the background process will allow the user to continue working while the PDF files are being created. You
    can upgrade your delegate to
    progress or create a temporary image which is replaced when the PDF file is created.)
  • d. Save the image in your application. directories (or photo libraries) using a unique identifier as a name.
  • e. If necessary, upload an image from disk to UIImageView or
    no matter what is appropriate.

For each pdf url

  • a.Draw the PDF.
  • b. Show UIImage view
  • c.Convert to PNG NSData (UIImagePNGRepresentation (image))
  • d.Save NSData in CoreData.
  • e.Load NSData and convert to UIImage if necessary.
0
source

All Articles