如何使用Core Data中的指针来持久保存c-struct

时间:2014-03-14 16:26:45

标签: objective-c core-data attributes

如何像GSL-Library中的结构一样持久保存C类型: 核心数据中的https://www.gnu.org/software/gsl/manual/html_node/Matrices.html

作为一个例子,我想知道如何使用gsl_matrix完成它。 它包含指针和嵌套结构。

typedef struct 
{
    size_t size1;
    size_t size2;
    size_t tda;
    double * data;
    gsl_block * block;
    int owner;
} gsl_matrix;

typedef struct
{
    size_t size;
    double *data;
}gsl_block;

编辑: Tom Harrington建议后的解决方案:

@interface Recipe : _Recipe 
@property gsl_matrix* matrix_;
@end

@implementation Recipe
@synthesize matrix_ = _matrix_;

/**
 *  Called once in it's lifetime
 *  when the object is created.
 */
- (void)awakeFromInsert
{
    [super awakeFromInsert];
    _matrix_ = gsl_matrix_calloc(11, 7);
}

/**
 *  Called everytime the object 
 *  is fetched from core-data.
 */
- (void)awakeFromFetch
{
    [super awakeFromFetch];
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:self.matrix];

    unsigned long size1 = [unarchiver decodeInt64ForKey: @"size1"];
    unsigned long  size2 = [unarchiver decodeInt64ForKey: @"size2"];
    _matrix_ = gsl_matrix_alloc(size1, size2);
    _matrix_->tda = size2;

    _matrix_->block->size = _matrix_->size1*_matrix_->size2;
    _matrix_->owner = [unarchiver decodeIntForKey:@"owner"];

    int savedEndianess = [unarchiver decodeIntForKey:@"endianess"];

    NSUInteger length;
    if (savedEndianess != currentEndianess()) {
        NSSwappedDouble *sw = (NSSwappedDouble *)[unarchiver decodeBytesForKey:@"data"
                                                                returnedLength:&length];
        for (int i = 0; i < _matrix_->block->size ; ++i) {
            _matrix_->data[i] = NSConvertSwappedDoubleToHost(sw[i]);
        }
    }
    else{
        _matrix_->data = (double *)[unarchiver decodeBytesForKey:@"data"
                                                  returnedLength: &length];
    }
}

- (void)willSave
{
    NSMutableData *archivedGslMatrix = [NSMutableData data];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archivedGslMatrix];
    [archiver encodeInt64:_matrix_->size1
                   forKey:@"size1"];

    [archiver encodeInt64:_matrix_->size2
                   forKey:@"size2"];

    [archiver encodeInt: currentEndianess() forKey:@"endianess"];

    [archiver encodeBytes:(u_int8_t *)_matrix_->data
                   length:sizeof(*(_matrix_->data))*_matrix_->block->size
                   forKey:@"data"];

    [archiver encodeInt64:_matrix_->owner
                   forKey:@"owner"];

    [archiver finishEncoding];
}

1 个答案:

答案 0 :(得分:0)

您需要编写一些自定义代码以将其转换为NSData,然后将其保存为托管对象的属性。可能最简单的方法是NSKeyedArchiver / NSKeyedUnarchiver。你会做类似的事情:

gsl_matrix currentMatrix = // ... passed in


NSMutableData *archivedGslMatrix = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archivedGslMatrix];
[archiver encodeInt:currentMatrix.size1 forKey:@"size1"];
[archiver encodeBytes:currentMatrix.data length:LENGTH_HERE forKey:@"data"];

... etc ...

[archiver finishEncoding];

[myManagedObject setValue:archivedGslMatrix forKey:@"matrix"];

另一方面,通过NSKeyedUnarchiver撤消流程。请注意,在解码像data这样的字段时,您需要将字节复制到您自己的malloc内存中。