跨设备的iOS中的32/64位CGPoint持久性

时间:2015-03-14 03:36:33

标签: ios objective-c core-data 64-bit cgpoint

我继承了一些徒手绘图代码,该代码记录了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:@"|"];
    }
}

它使得在平台之间解析也相当简单。

思想?

1 个答案:

答案 0 :(得分:0)

您可以选择floatdouble作为要保存的数据类型。这将显式设置大小,因为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

当然也有其他方法可以做到这一点。