Как хранить 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
По-моему, лучше хранить четыре значения отдельно.