选择后,图像不会显示在图像视图中

时间:2011-10-19 19:11:47

标签: ios sqlite core-data uiimageview picker

我正在尝试将图像保存在核心数据中但是在我在模拟器中选择后,它不会显示在图像视图中?以下是代码示例:

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if (fugitive_.image != nil) {
        self.fugitiveImage.image = [UIImage imageWithData:fugitive_.image];
    }
}

- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
   fugitive.image = UIImagePNGRepresentation([info objectForKey:UIImagePickerControllerEditedImage]);
    [self dismissModalViewControllerAnimated:YES];
    [picker release];
}

1 个答案:

答案 0 :(得分:9)

首先,不要在Core Data中存储图像(或任何二进制数据);特别是在iOS上。您将获得更好的性能,将其存储在磁盘上,然后在Core Data中存储对文件位置的引用。

其次,您的示例代码未显示如何将数据放入核心数据中。因此很难提出解决方案。

更新

我没有找到如何做到这一点的简单参考,所以这里有一个:

图像缓存Pre iOS 5.0

要在iOS 5.0之前的环境中在磁盘上设置图像缓存,首先要在实体上创建NSString的属性。在此示例中,我们将该属性命名为imageFilename。一旦完成,我们将要为我们的实体创建一个NSManagedObject的子类,以便我们可以实现帮助方法:

@interface MyEntity : NSManagedObject

@property (nonatomic, retain) NSString *imageFilename;
@property (nonatomic, retain) NSImage *image;

@end

我们将让Core Data管理imageFilename,因为它是在模型中定义的。但是,我们将实现image的访问者。

@implementation MyEntity

@dynamic imageFilename;

@synthesize image = _image;

- (void)setImage:(UIImage*)image
{
    NSString *filename = [self imageFilename];
    if (!filename) {
        filename = [[NSProcessInfo processInfo] globallyUniqueString];
        [self setImageFilename:filename];
    }

    [_image release];
    _image = [image retain];

    NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString *filePath = [cachePath stringByAppendingPathComponent:filename];
    NSData *data = UIImagePNGRepresentation(image);

    NSError *error = nil;
    if (![data writeToFile:filePath options:NSDataWritingAtomic error:&error]) {
        NSLog(@"Failed to write image to disk: %@\n%@", [error localizedDescription], [error userInfo]);
        return;
    }
}

-setImage:会将映像保存到磁盘缓存目录中(请注意,缓存目录未备份,并且在空间不足的情况下可由系统删除)。如果尚未创建一个随机文件名,它会选择一个随机文件名。

故意不存储路径,因为应用程序沙箱的目录可能会更改。因此,我们只想将文件名存储在Core Data中并解析路径。

我们还在内存中保留了对图像的引用,这样如果在此实体的生命周期中再次询问图像,我们就不会访问磁盘。这就是@synthesize的原因,即使我们正在实现访问器。

请注意,我们将图像作为PNG存储在磁盘上。这可能很昂贵(压缩程序相对较慢),但它使图像保持通用格式,这可能很有用。

- (UIImage*)image
{
    if (_image) return _image;
    NSString *filename = [self imageFilename];
    if (!filename) return nil;
    NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString *filePath = [cachePath stringByAppendingPathComponent:filename];

    if (![[NSFileManager defaultFileManager] fileExistsAtPath:filePath]) return nil;

    _image = [[UIImage alloc] initWithContentsOfFile:filePath];
    return _image;
}

-image的实施恰恰相反。我们检查一下我们是否有文件名;解析完整路径并将图像加载到内存中,然后将其返回给调用者。

- (void)prepareForDeletion
{
    [super prepareForDeletion];

    NSString *filename = [self imageFilename];
    if (!filename) return nil;
    NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString *filePath = [cachePath stringByAppendingPathComponent:filename];

    NSError *error = nil;
    if (![[NSFileManager defaultFileManager] removeItemAtPath:filePath error:&error]) {
        NSLog(@"Potential error removing on disk image: %@\n%@", [error localizedDescription], [error userInfo]);
    }
}

我们希望尽可能保持缓存目录的清洁,这样我们就不会创建低空间情况。因此,当要从Core Data中删除实体时,我们要从磁盘中删除该文件。删除期间发生的实际错误对我们来说是一个非致命的问题。这可能是一个错误,因为该文件已被删除或其他内容。没有理由为此错误完全失败,但记录它很重要。

- (void)willTurnIntoFault
{
    [super willTurnIntoFault];
    [_image release], _image = nil;
}

@end

最后,我们实现了-willTurnIntoFault方法,以便我们可以在此实体生命周期结束时释放对图像的内存引用。

图像缓存iOS 5.0 +

  1. 在实体上创建二进制属性。
  2. 打开“存储在外部记录文件中”位。
  3. 没有第三步