我继承了一些徒手绘图代码,该代码记录了CGPathRef
个点,然后转换为CGPoints
的集合,最终在我们的核心数据DB中保存为NSData
}。
当前转换代码如下所示:
@interface StoredPath : NSObject
{
CGPathRef path;
}
@implementation StoredPath
- (NSArray *)getPoints
{
// Convert path to an array
NSMutableArray *a = [NSMutableArray arrayWithObject:[NSNumber numberWithBool:YES]];
CGPathApply(path, (__bridge void *)(a), saveApplier);
if (![[a objectAtIndex:0] boolValue])
{
return nil;
}
[a removeObjectAtIndex:0];
return (a);
}
static void saveApplier(void *info, const CGPathElement *element)
{
NSMutableArray *a = (__bridge NSMutableArray*) info;
int nPoints;
switch (element->type)
{
case kCGPathElementMoveToPoint:
nPoints = 1;
break;
case kCGPathElementAddLineToPoint:
nPoints = 1;
break;
case kCGPathElementAddQuadCurveToPoint:
nPoints = 2;
break;
case kCGPathElementAddCurveToPoint:
nPoints = 3;
break;
case kCGPathElementCloseSubpath:
nPoints = 0;
break;
default:
[a replaceObjectAtIndex:0 withObject:[NSNumber numberWithBool:NO]];
return;
}
NSNumber *type = [NSNumber numberWithInt:element->type];
NSData *points = [NSData dataWithBytes:element->points length:nPoints*sizeof(CGPoint)];
[a addObject:[NSDictionary dictionaryWithObjectsAndKeys:type, @"type", points, @"points", nil]];
}
@end
这里要注意的重要部分是:
NSData *points = [NSData dataWithBytes:element->points length:nPoints*sizeof(CGPoint)];
它将CGPoint
数据保存到紧凑的NSData
对象中,然后将其保存在我们的核心数据DB中。
当应用程序的数据仅存在于单个设备上时,这很好。但是现在这些数据已同步到其他设备,但由于CGFloat
(组成CGPoint
结构)在各种iOS设备上为32位或64位而导致数据崩溃。
当在64位iOS设备上读取32位NSData of CGPoints
时,字节不会完全对齐,图形会受到损坏。反过来也是如此(在32位iOS设备上读取64位NSData of CGPoints
)。
我一直在努力以独立于平台的方式重构此saveApplier:
方法,并且可以轻松保存在核心数据中。
我考虑将点数打包成"|"
分隔的字符串。
示例:pointsToSave = {442, 797.5}|{442, 797.5}|{442, 797.5}
NSString *pointsToSave = [[NSString alloc] init];
// Convert CGPoint's to a "|" separated string.
for (int i=0; i<nPoints; i++)
{
pointsToSave = [pointsToSave stringByAppendingString:NSStringFromCGPoint(element->points[i])];
if ((i+1)<nPoints)
{
pointsToSave = [pointsToSave stringByAppendingString:@"|"];
}
}
它使得在平台之间解析也相当简单。
思想?
答案 0 :(得分:0)
您可以选择float
或double
作为要保存的数据类型。这将显式设置大小,因为float是32位而double是64位。
例如,如果您想要更紧凑,可以这样做:
float *floats = [self pointsToFloats:element->points];
NSData *points = [NSData dataWithBytes:floats length:nPoints*sizeof(float)*2];
free(floats); // Note will need to free, since assuming pointsToFloats uses malloc. Use delete if you use new.
pointsToFloats
的定义如下:
- (float *)pointsToFloats:(CGPoint *)points; // Assuming this is straight-forward enough to implement
这也意味着您还需要解压缩数据。
- (CGPoint *)floatsToPoints:(float *)floats;
如果您需要更高的精确度,也可以使用double
。
当然也有其他方法可以做到这一点。