I am trying to store image in core data using Transformable. The way I see it , I have been able to save the image in core data but the problem I have is retrieving it. Here's what I have done so far
//Custom subclass of NSManagedObject
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "ImageConverter.h"
@interface Image : NSManagedObject
@property (nonatomic, retain) id storedImage;
@end
#import "Image.h"
@implementation Image
@dynamic storedImage;
@end
//NSTransformable Subclass
#import <Foundation/Foundation.h>
@interface ImageConverter : NSValueTransformer
@end
#import "ImageConverter.h"
@implementation ImageConverter
+ (Class)transformedValueClass
{
return [NSData class];
}
+ (BOOL)allowsReverseTransformation
{
return YES;
}
- (id)transformedValue:(id)value
{
if (value == nil)
return nil;
// I pass in raw data when generating the image, save that directly to the database
if ([value isKindOfClass:[NSData class]])
return value;
return UIImagePNGRepresentation((UIImage *)value);
}
- (id)reverseTransformedValue:(id)value
{
return [UIImage imageWithData:(NSData *)value];
}
@end
//ViewController class where I save the image into core data and retrieve the image back on button click
#import <UIKit/UIKit.h>
#import "Image.h"
@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSManagedObjectContext *context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
Image *event = [NSEntityDescription insertNewObjectForEntityForName: @"Image" inManagedObjectContext:context];
// self.imageView.image = [UIImage imageNamed:@"Bus.png"];
event.storedImage = [UIImage imageNamed:@"Bus.png"];
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)button:(id)sender {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc]init];
// NSEntityDescription *entity= [NSEntityDescription entityForName:@“Event" inManagedObjectContext : context];
//
//
NSManagedObjectContext *context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Image" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *error ;
NSArray *fetchResults =
[context executeFetchRequest : fetchRequest error : &error];
for (Image *objects in fetchResults){
if(objects.storedImage != nil) {
NSLog(@"%@",objects.storedImage);
}
self.imageView.image = objects.storedImage
}
}
@end
I expect to see the retrieved image as
self.imageView.image = objects.storedImage.
But so far I have not been able to retrieve it. When I NSLog ImageCoreData[3253:108752] UIImage: 0x7fbec1560f70, {0, 0} is retrieved but no image is set on UIImageView.
Any help regarding this will be great. I am also confused about storing the video in core data. Please suggest the right way to approach it.
It's because you're using imageNamed:
to create the image. Due to an apparent bug in Core Data (or maybe keyed archives), images created this way can't be saved to Core Data transformable attributes. No errors occur, but you can't retrieve the image later on. (rdar://20717042
for anyone who might be interested).
If you create the image any other way then it should work. For example if you use imageWithContentsOfFile:
, you'll be fine. But you can't use imageNamed:
here.