Sam Kirkiles
Sam Kirkiles

Reputation: 27

App crashes due to memory error when images are held in a collection view from core data

I am adding images to a collection view from core data that takes in images from a uiimagepicker. However, when I load more than 6 images into my app, it takes up most of the memory and sometimes crashes. I am not doing anything to the images except fetching them and putting them straight into the collection view in cells that have 100x100 image views. Does anyone know what I can do to reduce the memory and make the app not crash?

Code snippets:

-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
    return 1;
}

-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    return _fetchedObjects.count;
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
        PhotosCollectionViewCell * cell = (PhotosCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"photoCell" forIndexPath:indexPath];
        NSManagedObject *object = [_fetchedObjects objectAtIndex:indexPath.row];
        cell.cellImage.image = [UIImage imageWithData:[object valueForKey:@"image"]];
        return cell;
}

Other class:

    Photo * photoEntity = [NSEntityDescription insertNewObjectForEntityForName:@"Photo" inManagedObjectContext:_context];
    NSError * error;
    NSData *imageData = UIImagePNGRepresentation(_image);
    photoEntity.name = _nameField.text;
    photoEntity.image = imageData;
    photoEntity.imagedescription = _descriptionField.text;
    if (![_context save:&error]) {
        NSLog(@"There was a save error:%@",error);
    }
    [self dismissViewControllerAnimated:YES completion:nil];

Thanks

Upvotes: 0

Views: 1095

Answers (2)

eofster
eofster

Reputation: 2047

You need to separate high-resolution image from the preview you use in the collection view.

Just extract the high-resolution data to a separate entity behind the relationship from Photo object. Let’s call this second entity ImageData. It will have a single attribute imageData with option “Allows external storage” checked. Photo will have a relationship to ImageData and ImageData will have an inverse relationship to Photo.

Photo will have a small version of the image. With the resolution just enough for the cells. It also doesn’t hurt to check “Allows external storage for it” so that Core Data would decide where to store it.

Now when you fetch your Photo objects for the collection view, you’ll load only small version of images. The relationship itself to the ImageData will be fault by default, and the object on the other side of the relationship will be fault.

When the user clicks the cell and you display some detail view controller, you’ll take this photo and just use its property to get the big image photo.imageData.imageData. And only at this moment does the fault fire and is the big image loaded into memory.

Upvotes: 1

matt
matt

Reputation: 535402

Do not store images in Core Data. They take up too much memory! If an object one of whose attributes is an image is read into memory, that image is read into memory. So if you've got 100 objects and you fetch their names, you have also loaded 100 images into memory, which can kill your app.

In Core Data, store references to images. Store the actual images somewhere else, e.g. on disk.

Upvotes: 4

Related Questions