2012-07-08 71 views
1

我的核心基金會類型&集合的工作經驗有限,所以如果這是顯而易見的道歉。如何使用CFData/NSData在CFData中存儲CFBitVector(或任何CFType)?

我使用CFBitVector類型來存儲一些比特序列,並且我需要將其存儲在一個二進制數據格式(以便它可以被添加到核心數據存儲)。最明智的做法似乎是這些信息存儲在一個CFData類型,可以是付費橋與NSData並添加到店,但我不確定如何做到這一點。

任何人可以幫助我在CF/NSData的存儲CFTypes的一個簡單的例子?


編輯:

這甚至是正確的做法?我應該嘗試將CFBitVector轉換成一系列可以存儲在數據模型中的int?或者可能是可變形的屬性?

回答

3

我最終這樣做的方式是滾動我自己的屬性變換器,以便將CFBitVectorRef轉換爲NSData實例。這樣做的好處是,我可以將位數組緊緊地塞入一塊二進制數據中,就像我的情況一樣,我真的需要將存儲大小降到最低。

下面是我CFBitVectorTransformer類的實現。它實際上讀取每一位並將它們打包成unsigned char(以下代碼中的「段」),然後將它們附加到可變緩衝區NSData。該代碼可用於大於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在數據模型中的屬性,應該是足夠快足以滿足大多數的目的。

我希望這有助於在類似情況下別人。

+0

我遇到了一個問題,即在' - (ID)reverseTransformedValue:(ID)value',當*位*應該是1,這似乎需要值,在2,4,64,128等,所以我需要手動執行'CFBitVectorSetBitAtIndex(bitVector,bitVectorBitIndex,bit!= 0)'。不知道這是一個錯誤還是我沒有正確使用代碼。 – BabyPanda 2015-06-23 11:19:10

相關問題