【问题标题】:Get notifications when an NSData/CFData object is being read?在读取 NSData/CFData 对象时获取通知?
【发布时间】:2016-06-04 23:10:42
【问题描述】:

我正在使用一个接受CFData 对象的API,我需要动态生成数据,这是一个耗时的操作。 CFData 由消费者以随机、非连续的方式读取,它实际上很少需要整个数据长度——它只需要其中的某些随机片段。

我想通过只实际生成消费者请求的位来提高性能。

有什么方法可以继承 CFData/NSData 以便在读取数据块时获得回调并即时生成它们?

更新:不幸的是,消费者是第 3 方代码,因此其他类不是一个选项,除非它们以某种方式神奇地与 CFData 兼容。

【问题讨论】:

  • 另一个需要考虑的替代方案是 CGDataProvider。
  • @jtbandes 不幸的是我无法控制消费者代码,它只接受 CFData。我刚刚更新了问题。
  • 好吧,如果没有一些严重的黑客行为,这可能是不可能的。第三方代码是开源的吗?你能写你自己的替代品吗?

标签: ios macos nsdata core-foundation cfdata


【解决方案1】:

我认为你不会喜欢你在这里得到的答案。您似乎在选择方面走投无路。

我们对您的情况的了解

  1. 客户端的代码不能接受不同的类型/类
  2. CFData 是 CoreFoundation C 类型,没有运行时可供使用
  3. 客户端可能使用 CoreFoundation 符号来读取此数据
    1. 如果幸运的话,它是通过 Obj-C 中的 Foundation API 实现的,它有一个运行时
  4. CFDatavoid * 包装到数据中,但如果您尝试创建 CFData 代理对象,则在开头有一些填充(可能是结构)将难以模仿

如果没有一些聪明的、不可维护的、总体上危险的符号黑客,我什至都不会费心去研究。

【讨论】:

    【解决方案2】:

    也许你想要的东西更像NSInputStream

    NSInputStream 是 NSStream 的子类,提供只读流 功能。

    NSInputStream 与其核心基金会“免费桥接” 对应的,CFReadStreamRef。有关免费电话的更多信息 桥接,请参阅免费桥接。

    子类化注释

    NSInputStream 是类簇的抽象超类,由 NSStream 的具体子类组成 提供对流数据的标准只读访问。虽然 NSInputStream 对于大多数需要的情况可能就足够了 访问流数据,你可以创建一个 NSInputStream 的子类,如果 您想要更专业的行为(例如,您想要记录 流中数据的统计信息)。

    【讨论】:

    • 请查看更新——不幸的是我无法控制消费者代码,因此在这种情况下无法切换到另一个类。
    【解决方案3】:

    CFDataRefNSData 是免费桥接的。这意味着,您可以将 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 我的子类的方法被调用。

    【讨论】:

      猜你喜欢
      • 2012-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多