Получать уведомления, когда объект NSData/CFData читается?
Я использую API, который принимает CFData
объект, и мне нужно генерировать данные на лету, что является трудоемкой операцией. CFData
читается потребителем случайным, несмежным образом, и на самом деле ему редко нужна вся длина данных - ему просто нужны определенные случайные фрагменты.
Я хотел бы улучшить производительность, только фактически генерируя биты, которые запрашивает потребитель, поскольку они запрашиваются.
Есть ли способ подкласса CFData
/NSData
чтобы я получал обратные вызовы при чтении фрагментов данных и генерировал их на лету?
Обновление: К сожалению, потребитель является сторонним кодом, и поэтому другие классы не являются опцией, если они каким-то образом магически не совместимы с CFData
,
3 ответа
Я не думаю, что вам понравятся ответы, которые вы получите здесь. Вы, кажется, загнаны в угол в отношении вариантов.
Что мы знаем о вашей ситуации
- Код клиента не может принимать другой тип / класс
CFData
является CoreFoundation C-type и не имеет времени выполнения для игры- Клиент, вероятно, использует символы CoreFoundation для чтения этих данных.
- Если вам повезет, это через API-интерфейсы Foundation в Obj-C, который имеет время выполнения
CFData
оборачиваетvoid *
к данным, но в начале имеет некоторые отступы (вероятно, структуру), которые будет трудно имитировать, если вы попытаетесь создатьCFData
объект прокси
Будет очень трудно выполнить то, что вы хотите, без каких-либо хитрых, необслуживаемых и в целом опасных хакерских символов, в которые я даже не буду лезть.
Возможно, вы хотите что-то более похожее NSInputStream
:
NSInputStream является подклассом NSStream, который обеспечивает функциональность потока только для чтения.
NSInputStream является "бесплатным мостом" со своим аналогом Core Foundation, CFReadStreamRef. Для получения дополнительной информации о бесплатном мостовом соединении см. Бесплатное мостовое соединение.
Примечания по подклассам
NSInputStream - это абстрактный суперкласс кластера классов, состоящий из конкретных подклассов NSStream, которые обеспечивают стандартный доступ только для чтения к потоковым данным. Хотя NSInputStream, вероятно, достаточно для большинства ситуаций, требующих доступа к потоковым данным, вы можете создать подкласс NSInputStream, если вы хотите более специализированное поведение (например, вы хотите записать статистику по данным в потоке).
CFDataRef
а также NSData
являются бесплатными мостами. Это означает, что вы можете пройти NSData
экземпляр в коде, который ожидает CFData
,
NSData
это кластер классов. Это означает, что вы можете создать его подкласс и реализовать только примитивные методы и инициализаторы. За NSData
Примитивные методы:
@property (readonly) NSUInteger length;
@property (readonly) const void *bytes NS_RETURNS_INNER_POINTER;
Вы также должны реализовать некоторые init
... метод, который инициализирует ваш экземпляр.
Все остальные NSData
функциональность предоставляется по категориям. Вы по-прежнему можете переопределить любой метод и предоставить собственную реализацию.
Как вариант, вы можете начать с NSData
подкласс, который будет делегировать любые методы внутренним NSData
экземпляр, который вы можете хранить в собственности. Таким образом, вы можете наблюдать за поведением стороннего кода и выяснить, какие методы вам нужно переопределить.
Тем не менее, вам нужно много удачи, чтобы реализовать то, что вы хотите. Но это может быть возможно.
В качестве примера я создал следующий манекен 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
метод моего подкласса называется.