CFDataRef
and NSData
are toll-free bridged. That mean, you can pass NSData
instance into code, that expect CFData
.
NSData
is a class cluster. That mean, you can subclass it, and implement only primitive methods and initializers. For NSData
primitive methods are:
@property (readonly) NSUInteger length;
@property (readonly) const void *bytes NS_RETURNS_INNER_POINTER;
You must also implement some init
... method, that will initialize your instance.
All other NSData
functionality is provided in categories. You still can override any method and provide your own implementation.
As an option, you can start from NSData
subclass that will delegate any methods to internal NSData
instance, which you can store in property. In this way you can observe 3rd party code behavior and investigate which methods you need to override.
Still, you will need a lot of luck to be able to implement what you want. But it may be possible.
As an example, I've created following dummy NSData
subclass:
@interface MyData : NSData
@property (nonatomic, strong) NSData *innerData;
@end
@implementation MyData
- (id)initWithData:(NSData *)data {
if (self = [super init]) {
_innerData = data;
}
return self;
}
- (NSUInteger)length {
NSLog(@"%@", NSStringFromSelector(_cmd));
return self.innerData.length;
}
- (const void *)bytes {
NSLog(@"%@", NSStringFromSelector(_cmd));
return self.innerData.bytes;
}
@end
When I invoke following code:
NSData *originalData = [NSData dataWithBytes:"hello" length:5];
MyData *myData = [[MyData alloc] initWithData:originalData];
NSLog(@"%ld", CFDataGetLength((CFDataRef)myData));
length
method of my subclass is called.