1

Core Foundation の型とコレクションを扱った経験は限られているため、これが明らかな場合は申し訳ありません。

CFBitVector 型を使用していくつかのビット シーケンスを格納していますが、バイナリ データ形式で格納する必要があります (コア データ ストアに追加できるようにするため)。最も賢明なことはCFData、これを型に格納することです。この型は、無料で とブリッジしNSDataてストアに追加できますが、これを行う方法がわかりません。

CF/NSData に CFTypes を格納する簡単な例を教えてくれる人はいますか?


編集:

これは正しいアプローチですか?CFBitVector を一連のints に変換して、データ モデルに格納できるようにする必要がありますか? それとも変形属性?

4

1 に答える 1

3

CFBitVectorRef私が最終的にこれを行った方法は、aをNSDataインスタンスに変換するために独自の属性トランスフォーマーをロールすることでした。これの利点は、ビット配列をバイナリ データのブロックにしっかりと詰め込むことができることです。私の場合は、ストレージ サイズを最小限に抑える必要があるためです。

以下は私のCFBitVectorTransformerクラスの実装です。基本的に各ビットを読み取り、それらをunsigned chars (以下のコードでは「セグメント」) にパックしてから、変更可能なNSDataバッファーに追加します。コードは s より大きい型で動作しますunsigned charが、結果のデータのサイズを実際に最小化するために、可能な限り最小のチャンクが必要でした。

#define kBitsPerByte    8


@implementation CFBitVectorTransformer


+ (Class)transformedValueClass
{
    return [NSData class];
}

+ (BOOL)allowsReverseTransformation
{
    return YES;
}

/* CFBitVectorRef -> NSData */
- (id)transformedValue:(id)value
{
    if (!value) return nil;
    if ([value isKindOfClass:[NSData class]]) return value;

    /* Prepare the bit vector. */
    CFBitVectorRef bitVector = (__bridge CFBitVectorRef)value;
    CFIndex bitVectorCount = CFBitVectorGetCount(bitVector);

    /* Prepare the data buffer. */
    NSMutableData *bitData = [NSMutableData data];
    unsigned char bitVectorSegment = 0;
    NSUInteger bytesPerSegment = sizeof(char);
    NSUInteger bitsPerSegment = bytesPerSegment * kBitsPerByte;

    for (CFIndex bitIndex = 0; bitIndex < bitVectorCount; bitIndex++) {
        /* Shift the bit into the segment the appropriate number of places. */
        CFBit bit = CFBitVectorGetBitAtIndex(bitVector, bitIndex);
        int segmentShift = bitIndex % bitsPerSegment;
        bitVectorSegment |= bit << segmentShift;

        /* If this is the last bit we can squeeze into the segment, or it's the final bit, append the segment to the data buffer. */
        if (segmentShift == bitsPerSegment - 1 || bitIndex == bitVectorCount - 1) {
            [bitData appendBytes:&bitVectorSegment length:bytesPerSegment];
            bitVectorSegment = 0;
        }
    }

    return [NSData dataWithData:bitData];
}

/* NSData -> CFBitVectorRef */
- (id)reverseTransformedValue:(id)value
{
    if (!value) return NULL;
    if (![value isKindOfClass:[NSData class]]) return NULL;

    /* Prepare the data buffer. */
    NSData *bitData = (NSData *)value;
    char *bitVectorSegments = (char *)[bitData bytes];
    NSUInteger bitDataLength = [bitData length];

    /* Prepare the bit vector. */
    CFIndex bitVectorCapacity = bitDataLength * kBitsPerByte;
    CFMutableBitVectorRef bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, bitVectorCapacity);
    CFBitVectorSetCount(bitVector, bitVectorCapacity);

    for (NSUInteger byteIndex = 0; byteIndex < bitDataLength; byteIndex++) {
        unsigned char bitVectorSegment = bitVectorSegments[byteIndex];

        /* Store each bit of this byte in the bit vector. */
        for (NSUInteger bitIndex = 0; bitIndex < kBitsPerByte; bitIndex++) {
            CFBit bit = bitVectorSegment & 1 << bitIndex;
            CFIndex bitVectorBitIndex = (byteIndex * kBitsPerByte) + bitIndex;
            CFBitVectorSetBitAtIndex(bitVector, bitVectorBitIndex, bit);
        }
    }

    return (__bridge_transfer id)bitVector;
}


@end

これにより、データの変換がうまく抽象化さCFBitVectorRefれ、データ モデルで を属性として設定するだけで済み、ほとんどの目的で十分に高速になるはずです。

これが同様の状況にある他の誰かに役立つことを願っています。

于 2012-07-09T04:56:01.133 に答える