Как хранить CGRect и другие вещи в основных данных

У меня есть несколько проблем с прорезями с 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 и добавлю новый привязанный "Значок", который будет NSManagedObject. Затем я добавляю свойство для textForBadge типа String. Все идет нормально. Я делаю что-то похожее для badgeValue, но потом приходим к UIColor и CGRect, и я немного тупик, поскольку для них нет свойства. Должен ли я создавать сущность для представления каждого (т.е. объект Rect, который имеет четыре свойства x,y,w,h), которые являются ints? Затем каждый раз заполняйте CGRect этими ints? Тоже для UIColor?

Наконец, я прихожу в список awards. Если это список указателей на ряд объектов, представляющих награду, они могут содержать изображение, цвет, текст и т.д. Я предполагаю, что award снова будет сущностью, которую я должен создать, а не Badge для хранения array У меня было бы от 1 до многих отношений от него до класса award.

Получаю ли я это право или собираюсь конкурировать в противоположном направлении? Все примеры, которые я вижу, работают с такими ванильными объектами, как String или int, поэтому я хочу, чтобы у меня было это прямо в голове, прежде чем реализовать кучу вещей.

С уважением,

Брина

Ответ 1

Это соответствующая документация: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdNSAttributes.html, но по существу, вы должны предоставить способ для Core Data переводить между вашим нестандартным свойства и виды вещей, которые он может хранить. Есть два способа сделать это. Либо используйте трансформируемые атрибуты и трансформаторы значений, либо используйте свойства переходных процессов, и выполняйте преобразование только тогда, когда будет сохранен контекст управляемого объекта.

Я думаю, что в большинстве случаев то, что вы описываете (определение пользовательских объектов для хранения компонентов чего-то типа CGRect), является излишним.

Ответ 2

В частности, в отношении CGRect вы можете использовать NSStringFromCGRect сохранить a CGRect как NSString. Затем используйте CGRectFromString для его преобразования:

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

Это позволяет легко хранить его в объекте NSManagedObject. Затем вы можете добавить пользовательский аксессуар в своей реализации, чтобы преобразовать его:

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

Ответ 3

Сохранение объектов и структур UIColor, таких как CGRect в Core Data, довольно просто (это может быть новым, поскольку OP спросил об этом):

Определите объекты как Transformable в вашей модели:

snapshot of Core Data model

В классах NSManagedObject определяют и обычно используют объекты UIColor:

@property (nonatomic, retain) UIColor *foreground;

textView.textColor = element.foreground;

Оберните структуры CGRect в объекте NSValue:

@property (nonatomic, retain) NSValue *imageRect;

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

Ответ 4

Вы должны быть осторожны, если используете сериализацию NSStringFromCGRect, предложенную aegzorz. Это не работает надежно для больших чисел, которые сокращаются в представлении 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

По-моему, лучше хранить четыре значения отдельно.