我正在使用一个接受CFData
对象的 API,我需要动态生成数据,这是一个耗时的操作。消费者以随机、非连续的CFData
方式读取它,它实际上很少需要数据的整个长度——它只需要其中的某些随机片段。
我想通过仅实际生成消费者请求的位来提高性能,因为它们是请求的。
有什么方法可以子类化CFData
/NSData
这样我会在读取数据块时得到回调并即时生成它们?
更新:不幸的是,消费者是第 3 方代码,因此其他类不是一个选项,除非它们以某种方式神奇地与CFData
.
我正在使用一个接受CFData
对象的 API,我需要动态生成数据,这是一个耗时的操作。消费者以随机、非连续的CFData
方式读取它,它实际上很少需要数据的整个长度——它只需要其中的某些随机片段。
我想通过仅实际生成消费者请求的位来提高性能,因为它们是请求的。
有什么方法可以子类化CFData
/NSData
这样我会在读取数据块时得到回调并即时生成它们?
更新:不幸的是,消费者是第 3 方代码,因此其他类不是一个选项,除非它们以某种方式神奇地与CFData
.
也许您想要更多类似的东西NSInputStream
:
NSInputStream 是 NSStream 的子类,提供只读流功能。
NSInputStream 与其 Core Foundation 对应的 CFReadStreamRef 是“免费桥接”的。有关免费桥接的更多信息,请参阅免费桥接。
子类化注释
NSInputStream 是类簇的抽象超类,由 NSStream 的具体子类组成,提供对流数据的标准只读访问。尽管 NSInputStream 对于大多数需要访问流数据的情况可能已经足够了,但是如果您想要更专业的行为(例如,您想要记录流中数据的统计信息),您可以创建 NSInputStream 的子类。
我不认为你会喜欢你在这里得到的答案。你似乎在选择方面走投无路。
CFData
是 CoreFoundation C 类型,没有运行时可供使用CFData
包装void *
数据,但在开始时有一些填充(可能是结构),如果您尝试创建CFData
代理对象,则很难模仿如果没有一些聪明的、不可维护的和整体危险的符号黑客,我什至都不会费心去研究,要完成你想要的事情将是非常困难的。
CFDataRef
并且NSData
是免费桥接的。这意味着,您可以将NSData
实例传递到代码中,即期望CFData
.
NSData
是一个类簇。这意味着,您可以对其进行子类化,并仅实现原始方法和初始化程序。对于NSData
原始方法是:
@property (readonly) NSUInteger length;
@property (readonly) const void *bytes NS_RETURNS_INNER_POINTER;
您还必须实现一些init
... 方法,该方法将初始化您的实例。
所有其他NSData
功能均按类别提供。您仍然可以覆盖任何方法并提供您自己的实现。
作为一种选择,您可以从NSData
将任何方法委托给内部NSData
实例的子类开始,您可以将其存储在属性中。通过这种方式,您可以观察 3rd 方代码行为并调查您需要覆盖哪些方法。
不过,你需要很多运气才能实现你想要的。但这可能是可能的。
例如,我创建了以下虚拟NSData
子类:
@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
当我调用以下代码时:
NSData *originalData = [NSData dataWithBytes:"hello" length:5];
MyData *myData = [[MyData alloc] initWithData:originalData];
NSLog(@"%ld", CFDataGetLength((CFDataRef)myData));
length
我的子类的方法被调用。