如果多次调用 NEPacketTunnelflow 方法 read Packets WithCompletionHandler 会发生什么情况?

What happens if the `NEPacketTunnelflow` method `readPacketsWithCompletionHandler` is called multiple times?

调用方法时

- (void)readPacketsWithCompletionHandler:(void (^)(
    NSArray<NSData *> *packets, NSArray<NSNumber *> *protocols))completionHandler;

如果数据包在调用时可用,则直接调用 completionHandler,或者在稍后数据包可用时调用。

然而没有任何记录的是:如果我在先前的集合 completionHandler 被调用之前再次调用此方法会发生什么?

新的处理程序是否会取代之前的处理程序并且根本不再调用之前的处理程序?

是否在数据到达时安排并调用了处理程序?如果是这样,它们会按照我传递给它们的顺序、相反的顺序还是随机的顺序被调用?

有人对该方法的实施方式有任何见解吗?

当然,我可以做一个演示项目,创建一个测试设置,然后看看我通过测试得到了什么结果,但这非常耗时,而且不一定可靠。未指定行为的问题在于它可能会在不让任何人知道的情况下随意更改。此方法在 macOS 和 iOS 上可能表现不同,它可能在每个新的 OS 版本中表现不同,或者取决于星期几。

或者没有记录任何内容是有意为之吗?我是否必须将其解释为:您可以调用此方法一次,在执行回调后,您可以使用相同或新的回调再次调用它。其他一切都是未定义的行为,如果以不同的方式使用API,你不能也不应该依赖任何特定的行为。

由于到目前为止还没有人回复,我尽力自己弄明白了。由于测试对我来说不够好,这是我所做的:

首先,我使用 this utility.

从 macOS Big Sur 的 dyld 缓存中提取了 NetworkExtension 框架二进制文件

然后我 运行 otool -Vt 遍历生成的二进制文件以获得二进制文件的反汇编转储。

我的组装技能有点生疏,但据我所知,completionHandler 存储在名为 packetHandler 的 属性 中,替换了之前存储的任何值。还在该方法中创建回调并存储在通过调用方法 interface.

获得的对象上

看这个创建回调的代码,获取了packetHandler属性的值,获取到后设置为NULL。然后它创建 NSDataNSNumber 对象,将它们添加到 NSArray 对象并使用这些数组调用获得的处理程序。

所以似乎再次调用该方法只是替换了以前的 completionHandler,在这种情况下永远不会调用它。因此,如果您的代码可能会替换隧道,如果隧道未被拆除,则您不能依赖计划的处理程序最终会在未来某个时间被调用。多次调用该方法以安排多个回调也没有效果,因为只有最后一个会被保留并最终被调用。