Reputation: 27
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
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
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