views:

67

answers:

3

Just a guess: I make an attribute and make it's type "binary". But in the end, how would I use that? I guess there is an NSData behind the scenes? So that attribute actually takes an NSData?

+1  A: 

That's correct, use binary which is represented as a NSdata object, then u can use uiimages imageWithData class method in order to retrieve your images.

Daniel
+3  A: 

This question has been asked a number of times and the answer is a bit more complex.

When it comes to binary data you should determine how to store it based on the expected size of data you are going to be working with. The rule is:

  • Less than 100K;store as a binary property in your main table
  • Less than 1M; store as a binary property in a ancillary table to avoid over fetching
  • Greater than 1M; store on disk and store its file path in the Core Data table.

In addition, when you are storing images, it is recommended to store them in a standard format such as JPG or PNG. By using the transformable property type you can actually have your subclass give the appearance of accessing the UIImage class when the actual store is a PNG representation. I go into this in detail in the bog post on Cocoa Is My Girlfriend.

Update

The reason behind storing > 1M binary data on disk is because of the cache. The NSPersistentStoreCoordinator will keep a cache of data so that when your app asks for the "next" object it doesn't need to go back out to disk. This cache works really well. However it is small, very small on iOS. If you pull in a big piece of binary data you can easily blow out that entire cache and your entire app suffers greatly.

Marcus S. Zarra
@Marcus, what's the reasoning behind storing images larger than 1M on disk instead of in Core Data?
kubi
Great article on CIMG. Thanks!
dontWatchMyProfile
A: 

Marcus's answer works, but it's not the easy way - and, AFAICT, it's not how Apple "intends" you to do it. In theory, you should be able to just mark the image as "Transformable", and CD would do everything automatically.

That doesn't work because UIImage is "missing" the implementation of NSCoding - Apple's serialization system - and so the default transformer from CD has no idea how to save an image.

The alternative, which requires a little code, but is still simpler than Marcus's approach ... allegedly you run into Apple's bugs. Apple's CoreData implementation (allegedly) has been broken since 2008 - the custom transformers are ignored for any data-store of type "Binary".

Going back to "CD would do everything automatically, if only UIImage were setup right" ... IMHO, UIImage ought to be serializable, even if the "Default" serialization isn't ideal for all cases. If you fix that, then lo and behold ... CoreData starts saving/laoding UIImage instances with zero coding from you.

Here's code to make your UIImage instances all serializable. All you have to do is import this category / copy paste this category into the classes where you want the "upgraded" UIImage version.

@implementation UIImage (MyCategory)

- (void)encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeDataObject:UIImagePNGRepresentation(self)];
}

- (id)initWithCoder:(NSCoder *)decoder
{
    NSData *data = [[decoder decodeDataObject] retain];

    return [[UIImage alloc] initWithData:data];
}

@end
Adam