Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data data model: attribute type for UIColor

I'm just starting out with Core Data and right now I'm building my data model. I need a UIColor attribute for my entity, but the type dropdown for the attribute doesn't have an option for this. Do I set it to Undefined or what?

Thanks

like image 953
indragie Avatar asked Feb 21 '10 05:02

indragie


People also ask

How do I store Uicolor in Core Data?

Fire up Xcode and create a new project based on the iOS > Single View App template. Name the project Colors and set Language to Swift. To save us some time, we also check Use Core Data at the bottom. Save the project and select the data model of the project, Colors.

What is attribute in Core Data?

You can think of attributes as the columns of a table in a database. Attributes store the values of a Core Data record. There are several types of attributes, such as String, Date, Integer, Float, and Boolean. Select the Note entity in the data model editor and click the + button at the bottom of the Attributes table.

What are Core Data types?

Core Data provides different attributes, including those common for all databases, such as Date or Decimal type, and non-standard attributes handled with Transformable type. It also provides Transient and Derived attributes so apps can derive one piece of data from the other.

How to use Transformable attribute in Core Data?

When you declare a property as Transformable Core Data converts your custom data type into binary Data when it is saved to the persistent store and converts it back to your custom data type when fetched from the store. It does this through a value transformer.


1 Answers

I'll paraphrase the definitve answer I found in More iPhone 3 Development by Dave Mark and Jeff LeMarche:

Usually we'd be able to leave the transformable attribute's transformer class as the default, NSKeyedUnarchiveFromData, and be done, but in this case we can't because UIColor doesn't conform to NSCoding and can't be archived using an NSKeyedArchiver. We have to manually write a value transformer to handle the transformation.

Add an attribute to your entity and call the attribute "color", or whatever name you wish. Set its type to Transformable. Set its "Value Transformer Name" to UIColorRGBValueTransformer. Note that the data model editor doesn't validate the Value Transformer Name: to make sure it's a valid class, so type carefully.

Create a new file, a subclass of NSObject, and name it UIColorRGBValueTransformer.m.

Click UIColorRGBValueTransformer.h and change the superclass from NSObject to NSValueTransformer. Also, change #import <Foundation/Foundation.h> to #import <UIKit/UIKit.h>, since UIColor is part of UIKit, not Foundation.

Now in UIColorRGBValueTransformer.m, we need to implement four methods that allow our value transformer class to convert instances of UIColor to NSData and vice versa. Include the following code in UIColorRGBValueTransformer.m:

#import "UIColorRGBValueTransformer.h"

@implementation UIColorRGBValueTransformer

// Here we override the method that returns the class of objects that this transformer can convert.
+ (Class)transformedValueClass {
    return [NSData class];
}

// Here we indicate that our converter supports two-way conversions.
// That is, we need  to convert UICOLOR to an instance of NSData and back from an instance of NSData to an instance of UIColor.
// Otherwise, we wouldn't be able to beth save and retrieve values from the persistent store.
+ (BOOL)allowsReversTransformation {
    return YES;
}

// Takes a UIColor, returns an NSData
- (id)transfomedValue:(id)value {
    UIColor *color = value;
    const CGFloat *components = CGColorGetComponents(color.CGColor);
    NSString *colorAsString = [NSString stringWithFormat:@"%f,%f,%f,%f", components[0], components[1], components[2], components[3]];
    return [colorAsString dataUsingEncoding:NSUTF8StringEncoding];
}

// Takes an NSData, returns a UIColor
- (id)reverseTransformedValue:(id)value {
    NSString *colorAsString = [[[NSString alloc] initWithData:value encoding:NSUTF8StringEncoding] autorelease];
    NSArray *components = [colorAsString componentsSeparatedByString:@","];
    CGFloat r = [[components objectAtIndex:0] floatValue];
    CGFloat g = [[components objectAtIndex:1] floatValue];
    CGFloat b = [[components objectAtIndex:2] floatValue];
    CGFloat a = [[components objectAtIndex:3] floatValue];
    return [UIColor colorWithRed:r green:g blue:b alpha:a];
}

@end

Now in another file, you can include a line of code like:

[self.managedObject setValue:color forKey:self.keyPath];

without needing to import UIColorRGBValueTransformer.h in the file.

like image 182
Rose Perrone Avatar answered Sep 21 '22 12:09

Rose Perrone