views:

275

answers:

1

I have an issue with memory usage relating to images and I've searched the docs and watched the videos from cs193p and the iphone dev site on memory mgmt and performance. I've searched online and posted on forums, but I still can't figure it out.

The app uses core data and simply lets the user associate text with a picture and stores the list of items in a table view that lets you add and delete items. Clicking on a row shows the image and related text. that's it.

Everything runs fine on the simulator and on the device as well. I ran the analyzer and it looked good, so i then starting looking at performance. I ran leaks and everything looked good. My issue is when running Object Allocations as every time i select a row and the view with the image is shown, the live bytes jumps up a few MB and never goes down and my app eventually crashes due to memory usage. Sorting the live bytes column, i see 2 2.72MB mallocs (5.45Mb total), 14 CFDatas (3.58MB total), 1 2.74MB malloc and everything else is real small. the problem is all the related info in instruments is really technical and all the problem solving examples i've seen are just missing a release and nothing complicated. Instruments shows Core Data as the responsible library for all but one (libsqlite3.dylib the other) with [NSSQLCore _prepareResultsFromResultSet:usingFetchPlan:withMatchingRows:] as the caller for all but one (fetchResultSetReallocCurrentRow the other) and im just not sure how to track down what the problem is. i've looked at the stack traces and opened the last instance of my code and found 2 culprits (below). I havent been able to get any responses at all on this, so if anyone has any tips or pointers, I'd really appreciate it!!!!

    //this is from view controller that shows the title and image
    - (void)viewWillAppear:(BOOL)animated 
    {
        [super viewWillAppear:animated];
    self.title = item.title;
    self.itemTitleTextField.text = item.title;
    if ([item.notes length] == 0) 
    {
        self.itemNotesTextView.hidden = YES;
    } else 
    {
        self.itemNotesTextView.text = item.notes;
    } //this is the line instruments points to
    UIImage *image = item.photo.image;
    itemPhoto.image = image;
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{
    if (editingStyle == UITableViewCellEditingStyleDelete) 
    {
        // Delete the managed object for the given index path
        NSManagedObjectContext *context = [fetchedResultsController managedObjectContext];
        [context deleteObject:[fetchedResultsController objectAtIndexPath:indexPath]];

        // Save the context.
        NSError *error = nil;
        if (![context save:&error]) //this is the line instruments points to
        {

            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            exit(-1);
        }
    }   
}
A: 

I suggest you to store image URL instead of image data itself. This prevent CoreData to work with and cache big data.

Skie
thanks for the help, any more specifics? would i have to totally change my core data data model to have one of the attributes be a url instead of an image?
Andrew Gray
Yes, try avoid storing big data objects in CoreData. It would be more effective. Also you can add custom methods to itemPhoto class for loading and caching images from URLs.
Skie
How do you generate URLs for images? I mean how do you choose where to store these?
Kamchatka
You must think of that yourself. For example you can use autoincrenment field in Core Data object (like /1.png, /2.png, ... /n.png) or use UUID string.
Skie