2012-07-08 6 views
1

Core Foundation 유형 & 콜렉션에 대한 작업 경험이 제한되어 있으므로 이것이 분명한 경우 사과하십시오.CFData/NSData를 사용하여 코어 데이터에 CFBitVector (또는 임의의 CFType)를 저장하는 방법?

일부 비트 시퀀스를 저장하기 위해 CFBitVector 형식을 사용하고 있으며이를 코어 데이터 저장소에 추가 할 수 있도록 이진 데이터 형식으로 저장해야합니다. 가장 현명한 것은 CFData 유형으로 이것을 저장하는 것인데, 수신자 부담 전화는 NSData으로 연결되어 매장에 추가 될 수 있지만이 작업을 수행하는 방법은 확실하지 않습니다.

CF/NSData에 CFTypes를 저장하는 간단한 예제를 통해 나를 도울 수 있습니까?


편집 :

이도 올바른 접근 방식인가? CFBitVector를 데이터 모델에 저장 될 수있는 일련의 int으로 변환해야합니까? 아니면 변형 가능한 속성일까요?

답변

3

내가이 일을 끝낸 방식은 CFBitVectorRefNSData 인스턴스로 변환하기 위해 자체 특성 변환기를 롤업하는 것이 었습니다. 이것의 이점은 비트 배열을 바이너리 데이터의 블록에 단단히 밀어 넣을 수 있다는 것입니다. 필자의 경우에는 스토리지 크기를 최소한으로 유지해야합니다.

다음은 내 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', * bit *가 1 일 때, 2,4,64,128 등의 값을 얻었습니다. 'CFBitVectorSetBitAtIndex (bitVector, bitVectorBitIndex, bit! = 0)'을 수동으로 할 필요가있다. 버그인지 또는 코드를 올바르게 사용하지 않았는지 확실하지 않습니다. – BabyPanda