在读取 NSData/CFData 对象时收到通知?
Get notifications when an NSData/CFData object is being read?
我正在使用带有 CFData
对象的 API,我需要动态生成数据,这是一项耗时的操作。 CFData
由消费者以随机、非连续的方式读取,它实际上很少需要数据的整个长度——它只需要其中的某些随机片段。
我想通过只实际生成消费者请求的位来提高性能。
有什么方法可以对 CFData
/NSData
进行子类化,以便在读取数据块时获得回调并即时生成它们?
更新: 不幸的是,消费者是第 3 方代码,因此其他 类 不是一个选项,除非它们以某种方式神奇地与 [=11= 兼容].
也许您想要更像 NSInputStream
:
NSInputStream is a subclass of NSStream that provides read-only stream
functionality.
NSInputStream is “toll-free bridged” with its Core Foundation
counterpart, CFReadStreamRef. For more information on toll-free
bridging, see Toll-Free Bridging.
Subclassing Notes
NSInputStream is an abstract superclass of a class cluster consisting of concrete subclasses of NSStream that
provide standard read-only access to stream data. Although
NSInputStream is probably sufficient for most situations requiring
access to stream data, you can create a subclass of NSInputStream if
you want more specialized behavior (for example, you want to record
statistics on the data in a stream).
我认为您不会喜欢这里的答案。您似乎在选项方面走投无路。
我们对您情况的了解
- 客户的代码不能接受不同的类型/class
CFData
是 CoreFoundation C 类型,没有可运行的运行时
- 客户端可能使用 CoreFoundation 符号来读取此数据
- 如果幸运的话,它是通过具有运行时的 Obj-C 中的 Foundation APIs
CFData
将 void *
包装到数据中,但在开头有一些填充(可能是结构),如果您尝试创建 CFData
将很难模仿代理对象
如果没有一些聪明的、不可维护的、整体危险的符号黑客技术,我将很难完成你想要的,我什至懒得去研究。
CFDataRef
和 NSData
是免费桥接。这意味着,您可以将 NSData
实例传递给期望 CFData
.
的代码
NSData
是一个 class 集群。这意味着,您可以 subclass 它,并且只实现原始方法和初始化器。 NSData
原始方法是:
@property (readonly) NSUInteger length;
@property (readonly) const void *bytes NS_RETURNS_INNER_POINTER;
您还必须实施一些 init
... 方法,这将初始化您的实例。
所有其他 NSData
功能均按类别提供。您仍然可以覆盖任何方法并提供您自己的实现。
作为一个选项,您可以从 NSData
subclass 开始,它将任何方法委托给内部 NSData
实例,您可以将其存储在 属性 中。通过这种方式,您可以观察第 3 方代码行为并调查您需要覆盖哪些方法。
不过,你需要很多运气才能实现你想要的。但有可能。
例如,我创建了以下虚拟 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
当我调用以下代码时:
NSData *originalData = [NSData dataWithBytes:"hello" length:5];
MyData *myData = [[MyData alloc] initWithData:originalData];
NSLog(@"%ld", CFDataGetLength((CFDataRef)myData));
length
调用了我的子方法class。
我正在使用带有 CFData
对象的 API,我需要动态生成数据,这是一项耗时的操作。 CFData
由消费者以随机、非连续的方式读取,它实际上很少需要数据的整个长度——它只需要其中的某些随机片段。
我想通过只实际生成消费者请求的位来提高性能。
有什么方法可以对 CFData
/NSData
进行子类化,以便在读取数据块时获得回调并即时生成它们?
更新: 不幸的是,消费者是第 3 方代码,因此其他 类 不是一个选项,除非它们以某种方式神奇地与 [=11= 兼容].
也许您想要更像 NSInputStream
:
NSInputStream is a subclass of NSStream that provides read-only stream functionality.
NSInputStream is “toll-free bridged” with its Core Foundation counterpart, CFReadStreamRef. For more information on toll-free bridging, see Toll-Free Bridging.
Subclassing Notes
NSInputStream is an abstract superclass of a class cluster consisting of concrete subclasses of NSStream that provide standard read-only access to stream data. Although NSInputStream is probably sufficient for most situations requiring access to stream data, you can create a subclass of NSInputStream if you want more specialized behavior (for example, you want to record statistics on the data in a stream).
我认为您不会喜欢这里的答案。您似乎在选项方面走投无路。
我们对您情况的了解
- 客户的代码不能接受不同的类型/class
CFData
是 CoreFoundation C 类型,没有可运行的运行时- 客户端可能使用 CoreFoundation 符号来读取此数据
- 如果幸运的话,它是通过具有运行时的 Obj-C 中的 Foundation APIs
CFData
将void *
包装到数据中,但在开头有一些填充(可能是结构),如果您尝试创建CFData
将很难模仿代理对象
如果没有一些聪明的、不可维护的、整体危险的符号黑客技术,我将很难完成你想要的,我什至懒得去研究。
CFDataRef
和 NSData
是免费桥接。这意味着,您可以将 NSData
实例传递给期望 CFData
.
NSData
是一个 class 集群。这意味着,您可以 subclass 它,并且只实现原始方法和初始化器。 NSData
原始方法是:
@property (readonly) NSUInteger length;
@property (readonly) const void *bytes NS_RETURNS_INNER_POINTER;
您还必须实施一些 init
... 方法,这将初始化您的实例。
所有其他 NSData
功能均按类别提供。您仍然可以覆盖任何方法并提供您自己的实现。
作为一个选项,您可以从 NSData
subclass 开始,它将任何方法委托给内部 NSData
实例,您可以将其存储在 属性 中。通过这种方式,您可以观察第 3 方代码行为并调查您需要覆盖哪些方法。
不过,你需要很多运气才能实现你想要的。但有可能。
例如,我创建了以下虚拟 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
当我调用以下代码时:
NSData *originalData = [NSData dataWithBytes:"hello" length:5];
MyData *myData = [[MyData alloc] initWithData:originalData];
NSLog(@"%ld", CFDataGetLength((CFDataRef)myData));
length
调用了我的子方法class。