- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我们的 C++ 应用程序使用 FSEventStream 以文件级粒度监视文件系统(使用 kFSEventStreamCreateFlagFileEvents 标志创建流),每个卷一个监听器。但是,Apple FSEvent API 中似乎存在一些错误/错误功能,这源于它们在将事件发送给我们之前如何从流中压缩(删除重复)事件:
次要,但很烦人:当使用以前的事件 ID 作为起点启动流时(为了捕获 self 们上次监视以来对文件系统的更改),提供的事件顺序是与我们在事件发生时监听事件所得到的不同,因为事件不是按 eventId 顺序到达,而是按文件名按字母数字顺序排序。我们通过在处理集合之前将所有历史事件累积在一个 id 排序列表中来解决这个问题。
主要:如果重命名事件发生得足够快,回调函数中提供给我们的实际事件并不代表文件系统上实际发生的事情。考虑我们交换目录名称的测试用例:
一个。更改文件
将其父目录重命名为 _temp
将另一个目录重命名为以前父目录的名称
将 _temp 重命名为步骤 c 中的目录。
如果我们在每个步骤之间放置 50 毫秒的延迟(本质上,任何保证给定事件不会与另一个事件在同一回调中的延迟),我们就会得到正确的事件序列(重命名显示作为事件对):
fsEventsCallback: Received FSEvents callback with 1 events:
fsEventsCallback: ID=34303406 PATH= /Users/stebro/swaptest/subdir1/file_1.txt FLAGS=kFSEventStreamEventFlagItemInodeMetaMod, kFSEventStreamEventFlagItemIsFile, kFSEventStreamEventFlagItemModified
fsEventsCallback: Received FSEvents callback with 2 events:
fsEventsCallback: ID=34303436 PATH= /Users/stebro/swaptest/subdir1 FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
fsEventsCallback: ID=34303437 PATH= /Users/stebro/swaptest/subdir1_temp FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
fsEventsCallback: Received FSEvents callback with 2 events:
fsEventsCallback: ID=34303620 PATH= /Users/stebro/swaptest/subdir2 FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
fsEventsCallback: ID=34303621 PATH= /Users/stebro/swaptest/subdir1 FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
fsEventsCallback: Received FSEvents callback with 2 events:
fsEventsCallback: ID=34303741 PATH= /Users/stebro/swaptest/subdir1_temp FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
fsEventsCallback: ID=34303742 PATH= /Users/stebro/swaptest/subdir2 FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
然而,在没有延迟的情况下(或者延迟足够小以至于多个重命名事件将在同一个回调调用中到达),操作系统似乎正在使用删除它认为是冗余事件的“优势”,结果在这个困惑中:
fsEventsCallback: Received FSEvents callback with 4 events:
fsEventsCallback: ID=34251572 PATH= /Users/stebro/swaptest/subdir1/file_1.txt FLAGS=kFSEventStreamEventFlagItemInodeMetaMod, kFSEventStreamEventFlagItemIsFile, kFSEventStreamEventFlagItemModified
fsEventsCallback: ID=34251580 PATH= /Users/stebro/swaptest/subdir1 FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
fsEventsCallback: ID=34251583 PATH= /Users/stebro/swaptest/subdir1_temp FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
fsEventsCallback: ID=34251584 PATH= /Users/stebro/swaptest/subdir2 FLAGS=kFSEventStreamEventFlagItemIsDir, kFSEventStreamEventFlagItemRenamed
我们可以做些什么来抑制这种压缩?我们正在使用此调用创建流:
FSEventStreamCreateRelativeToDevice(kCFAllocatorDefault,
&fsEventsCallback,
&context,
device,
reinterpret_cast<CFArrayRef>(_monitoredPaths),
lastEventId,
0, // Latency - problem exists with values of 1, 0.1 and 3 as well
kFSEventStreamCreateFlagFileEvents | kFSEventStreamCreateFlagNoDefer);
最佳答案
过度激进的事件折叠的解决方案可以使用 kFSEventStreamCreateFlagUseExtendedData
(自 OS X 10.13 起可用)。使用该标志创建的流将包含事件文件的 inode。这样您就可以检测报告的事件批处理中发生的“重命名链”。
附言我在我的文件监视器中尝试了你的场景;事件顺序是正确的。
关于c++ - 如何解决 FSEventStream 中损坏的事件压缩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43638230/
我正在编写一个应用程序,将数据保存到特定文件夹内的一组文本文件中。当其他应用程序(例如 Dropbox 或 TextEdit)更改文件时,我有一个 FSEventStream 会收到通知,这样我就可以
我正在使用 OSX FSEventStream 监视特定目录中的文件系统更改。我正在查看文档 here我发现了一个有趣的标志,kFSEventStreamCreateFlagIgnoreSelf。 根
我们的 C++ 应用程序使用 FSEventStream 以文件级粒度监视文件系统(使用 kFSEventStreamCreateFlagFileEvents 标志创建流),每个卷一个监听器。但是,A
我在 XPC 服务中使用 FSEventStream 时遇到了很大的麻烦(代码如下)。服务启动,创建流,但从未调用回调函数。当我将完全相同的代码复制到主应用程序并运行它时,它工作得很好。它在 XPC
我已经成功地掌握了 FSEventStream 的基础知识,可以让我监视文件夹中的新文件事件。不幸的是,我传递给 FSEventStreamCreate() 的回调引用正在丢失/损坏/未保留,因此我也
我是一名优秀的程序员,十分优秀!