如何在核心数据中存储CGRect和其他东西

时间:2010-10-11 17:49:00

标签: iphone objective-c core-data ios4

我在coredata上遇到了一些问题,但如果有人能向我解释一些简单的案例,我觉得这会让我感到很清楚。

我想把我的模型放到coredata中,并且在最简单的情况下利用undo / redo。事实是,我看到的所有例子都倾向于存储字符串或整数。如果我想要在核心数据中实现如下的类(一个组成的示例),那该怎么办:

@interface Badge : NSObject {

NSString *textForBadge;
int      badgeValue;
UIColor  *color;
CGRect    rect;
NSMutableArray *awards; // this would be a list of 'Category' - another custom class
}

这些都是当场制作的,但每一个都突出了一个混乱

在我看来,我会打开.xcdatamodel并添加一个新的Entity caled'Badge',这将是NSManagedObject。然后,我为textForBadge类型String添加了一个属性。到现在为止还挺好。我为badgeValue做了类似的事情,但随后来到UIColorCGRect并且我有点难过,因为那里没有属性。我是否应该创建一个实体来表示每个(即具有四个属性Rect的{​​{1}}实体)的实体?然后每次用这些整数填充CGRect?同样适用于UIColor?

最后,我来到我的x,y,w,h列表。如果这些是指向表示奖励的多个对象的指针列表,则它们可能包含图像,颜色,文本等。我​​假设awards将再次成为我必须设计的实体,而不是{{1存储一个数组我将从它到award类之间有一对多的关系。

我是否正确地做到这一点,或者是在相反的方向上进行竞争?我看到的所有例子都在像String或int这样的vanilla对象上运行,所以我想在实现一堆东西之前确保我的脑子里有这个。

亲切的问候,

布林

4 个答案:

答案 0 :(得分:23)

特别是关于CGRect,您可以使用NSStringFromCGRectCGRect存储为NSString。 然后使用CGRectFromString将其转换回来:

CGRect rect = CGRectMake( 5, 5, 40, 30 );
NSString* rectAsString = NSStringFromCGRect( rect );
CGRect original = CGRectFromString( rectAsString );

这使您可以轻松地将其存储在NSManagedObject中。 然后,您可以在实现中添加自定义访问器以进行转换:

- (CGRect)realRect {
    return CGRectFromString( self.rectAsString );
}

答案 1 :(得分:17)

在Core Data中存储像CGRect这样的UIColor对象和结构相当容易(这可能是新的,因为OP询问了它):

在模型中将对象定义为Transformable:

snapshot of Core Data model

在NSManagedObject类中,通常定义和使用UIColor对象:

@property (nonatomic, retain) UIColor *foreground;

textView.textColor = element.foreground;

在NSValue对象中包装CGRect结构:

@property (nonatomic, retain) NSValue *imageRect;

CGRect imageRect = [self.imageRect CGRectValue];
imageRect.size.width = 100;
self.imageRect = [NSValue valueWithCGRect:imageRect];

答案 2 :(得分:9)

如果使用aegzorz建议的NSStringFromCGRect序列化,则必须小心。对于在NSString表示中缩写的大数字,这不能可靠地工作。

例如,此代码

CGRect test1 = CGRectMake(CGFLOAT_MAX, CGFLOAT_MAX, CGFLOAT_MAX, CGFLOAT_MAX);
NSString* test1Str = NSStringFromCGRect(test1);
CGRect test2 = CGRectFromString(test1Str);
NSLog(@"test1: %f %f %f %f", test1.origin.x - CGFLOAT_MAX, test1.origin.y - CGFLOAT_MAX, test1.size.width - CGFLOAT_MAX, test1.size.height - CGFLOAT_MAX);
NSLog(@"test2: %f %f %f %f", test2.origin.x - CGFLOAT_MAX, test2.origin.y - CGFLOAT_MAX, test2.size.width - CGFLOAT_MAX, test2.size.height - CGFLOAT_MAX);

将输出

test1: 0.000000 0.000000 0.000000 0.000000
test2: -344800963262078397207103271862272.000000 -344800963262078397207103271862272.000000 -344800963262078397207103271862272.000000 -344800963262078397207103271862272.000000

在我看来,最好分别存储四个值。

答案 3 :(得分:6)

这是相关文档:http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdNSAttributes.html但实际上,您必须为Core Data提供一种在非标准属性和它可以存储的内容之间进行转换的方法。有两种方法可以做到这一点。使用可转换属性和值转换器,或使用瞬态属性并仅在要保存托管对象上下文时执行转换。

我认为在大多数情况下,您所描述的内容(定义用于存储CGRect等组件的自定义实体)是过度的。