当图像保存在核心数据的集合视图中时,应用程序因内存错误而崩溃

Posted

技术标签:

【中文标题】当图像保存在核心数据的集合视图中时,应用程序因内存错误而崩溃【英文标题】:App crashes due to memory error when images are held in a collection view from core data 【发布时间】:2014-01-20 04:09:08 【问题描述】:

我正在从核心数据中将图像添加到集合视图中,该核心数据从 uiimagepicker 中获取图像。但是,当我将超过 6 张图像加载到我的应用程序中时,它会占用大部分内存,有时还会崩溃。除了获取它们并将它们直接放入具有 100x100 图像视图的单元格中的集合视图之外,我没有对图像做任何事情。有谁知道我可以做些什么来减少内存并使应用程序不会崩溃?

代码sn-ps:

-(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;

其他类:

    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];

谢谢

【问题讨论】:

存储的图像大小是多少?如果图像视图为 100 x 100,则显示时需要缩小图像尺寸。 @iCoder 我希望在您单击图像时仍然保持更高的分辨率。可以两者兼得吗? 我已经回答了同样的问题 [这里][1] [1]:***.com/questions/17161755/…希望这会有所帮助! 你的图片是什么格式的,尺寸是多少? 【参考方案1】:

不要将图像存储在 Core Data 中。他们占用了太多的内存!如果将属性之一是图像的对象读入内存,则将该图像读入内存。因此,如果您有 100 个对象并获取它们的名称,那么您还会将 100 个图像加载到内存中,这可能会导致您的应用程序崩溃。

在 Core Data 中,将 references 存储到图像。将实际图像存储在其他地方,例如在磁盘上。

【讨论】:

我是否使用 xcdata 文件中的允许外部存储选项来执行此操作? @Sam:我认为 matt 的意思是你应该只将文件路径存储在 Core Data 中,而不是实际的图像文件。【参考方案2】:

您需要将高分辨率图像与您在集合视图中使用的预览分开。

只需将高分辨率数据从Photo 对象中提取到关系背后的单独实体即可。我们称这第二个实体为ImageData。它将有一个属性imageData 并选中“允许外部存储”选项。 PhotoImageData 有关系,ImageDataPhoto 有反比关系。

Photo 将有一个小版本的图像。分辨率刚好够细胞使用。勾选“Allows external storage for it”也没有什么坏处,Core Data 会决定在哪里存储它。

现在,当您为集合视图获取 Photo 对象时,您将只加载小版本的图像。默认情况下,ImageData 的关系本身会出错,关系另一端的对象也会出错。

当用户单击单元格并显示一些细节视图控制器时,您将拍摄这张照片并使用它的属性来获取大图像photo.imageData.imageData。并且只有在这个时候故障才触发,并且大图像被加载到内存中。

【讨论】:

以上是关于当图像保存在核心数据的集合视图中时,应用程序因内存错误而崩溃的主要内容,如果未能解决你的问题,请参考以下文章

当更新版本已经在内存中时,强制核心数据从以前存储的版本刷新 NSManagedObject

当我们保存在 NSUserDefaults 中时,从核心数据和应用程序中获取“<NULL>”数据会崩溃?

如何在核心数据中保存图像的引用(图像 URL 或路径)并在以后需要时加载?

来自核心数据的集合视图 - 最后选择的内容首先出现

IOS App 将图像保存在内存中

当我尝试将用户上传的图像保存在视图中时,为啥 ImageField 中的 upload_to 根本不起作用