MacOS文件监控

概述

在File System 事件中,当文件目录层次结构的内容发生变化时,获取通知。即提供了监听文件功能。

文件系统事件API提供了一种方法,让应用程序在目录层次结构的内容被修改时请求通知。例如,您的应用程序可以使用它来快速检测用户何时使用另一个应用程序修改了项目包中的文件。
它还提供了一种轻量级的方法来确定自应用程序上次检查目录层次结构的内容之后,目录层次结构的内容是否发生了更改。例如,备份应用程序可以使用它来确定自给定时间戳或给定事件ID以来哪些文件发生了更改。

相关API翻译

1.FSEventStreamCreate

使用给定的参数创建一个新的FS事件流对象,为了可以接受事件通知,必须调用FSEventStreamScheduleWithRunLoop()FSEventStreamStart()函数。

allocator:用于为流分配内存,可以通过NULL或者kCFAllocatroDefault来使用当前默认值。

callBack:FS事件发生时,一个函数回调。

context:指向客户端的 FSEventStreamContext 结构的指针
它会与这个流相关联。然后它的字段被复制出来进入流本身,以便在创建流后可以释放其内存。允许传递 NULL 如果传递NULL则等同于传递一个字段都设置为零的结构。

pathsToWatch:每个CFStringRef指定一个目录的路径,表示要监视修改的文件系统层次结构的根。

sinceWhen:该服务将提供在给定事件id之后发生的事件。通常,客户端会提供他们在回调中收到的最高编号FSEventStreamEventId,他们可以通过 FSEventStreamGetLatestEventId()访问器来获取,不要传0值,除非你想接受自“时间开始”以来修改的每一个目录事件。

latency:服务在从内核得知某个事件后,通过回调将其传递给客户端之前,应该等待的秒数。指定较大的值可能会导致更有效的临时合并,从而减少回调,提高总体效率。如果为10s,则10s交付一次事件。

flag:修改正在创建的流的行为的标志,具体可以看FSEventStreamCreateFlags枚举

func FSEventStreamCreate(_ allocator: CFAllocator?, _ callback: FSEventStreamCallback, _ context: UnsafeMutablePointer<FSEventStreamContext>?, _ pathsToWatch: CFArray, _ sinceWhen: FSEventStreamEventId, _ latency: CFTimeInterval, _ flags: FSEventStreamCreateFlags) -> FSEventStreamRef?

2.FSEventStreamCopyDescription

传入一个事件流,包含所提供流的描述的CFStringRef,

func FSEventStreamCopyDescription(_ streamRef: ConstFSEventStreamRef) -> CFString

例如:我传入一个FSEventStreamRef,它的描述如下

FSEventStreamRef @ 0x11ef04d40:
   allocator = 0x1f1cd88c0
   callback = 0x100c7aa74
   context = {0, 0x600000294c80, 0x0, 0x0, 0x0}
   numPathsToWatch = 1
   pathsToWatch = 0x600002e9c210
        pathsToWatch[0] = '/System/Volumes/Data/Users/wzf/Desktop/test1'
   latestEventId = 5642644
   latency = 1000000 (microseconds)
   flags = 0x00000011
    runLoop = 0x600001084400
    runLoopMode = 0x1f1ce52a8

3.FSEventStreamCopyPathsBeingWatched

返回创建流时提供的那些目录路径

func FSEventStreamCopyPathsBeingWatched(_ streamRef: ConstFSEventStreamRef) -> CFArray

示例如下:

po FSEventStreamCopyPathsBeingWatched(self.syncEventStream)
<__NSSingleObjectArrayI 0x600002e9c3a0>(
/Users/wzf/Desktop/test1

4.FSEventStreamCreateRelativeToDevice

使用给定的参数为特定设备创建一个新的FS事件流对象。与FSEventStreamCreate相比,它可以指定一个特定的设备去监听。

deviceToWatch:dev_t对应于您想要收到通知的设备,dev_t与该设备上文件stat结构中的st_dev字段或者statfs结构中的f_fsid[0]字段相同。如果dev的值为0,则忽略。

pathsToWatchRelativeToDevice: 每个目录路径为指定设备的dev参数标识的目录的相对路径。路径应该相对于设备的根。例如,如果一个卷“MyData”挂载在“/Volumes/MyData”,而你想要观看“/Volumes/MyData/Pictures/July”,则需要指定一个路径字符串“Pictures/July”。要观察一个卷的根通过一个路径“”(空字符串)。。

func FSEventStreamCreateRelativeToDevice(_ allocator: CFAllocator?, _ callback: FSEventStreamCallback, _ context: UnsafeMutablePointer<FSEventStreamContext>?, _ deviceToWatch: dev_t, _ pathsToWatchRelativeToDevice: CFArray, _ sinceWhen: FSEventStreamEventId, _ latency: CFTimeInterval, _ flags: FSEventStreamCreateFlags) -> FSEventStreamRef?

5.FSEventStreamFlushAsync

根据FS事件流对象返回一个最大的事件id,如果流中没有事件排队,则为0。

要求FS Events服务清除已发生但由于在创建流时提供的延迟参数而尚未交付的任何事件。由于此刷新是异步发生的——不保证在此调用完成时,事件已经交付给回调监听函数。

注意:这个函数必须在FSEventStreamStart()之后调用。

func FSEventStreamFlushAsync(_ streamRef: FSEventStreamRef) -> FSEventStreamEventId

示例:

po FSEventStreamFlushAsync(self.syncEventStream)
5858865

6.FSEventStreamFlushSync

要求FS Events服务清除已发生但由于在创建流时提供的延迟参数而尚未交付的任何事件。这个刷新是同步发生的——所以当这个调用返回时,已经发生的事件会回调给监听函数。

注意:这个函数必须在FSEventStreamStart()之后调用。

FSEventStreamFlushSync(_ streamRef: FSEventStreamRef)

7.FSEventStreamGetDeviceBeingWatched

获取FSEventStreamCreateRelativeToDevice创建流时提供的dev_t,否则为0。

func FSEventStreamGetDeviceBeingWatched(_ streamRef: ConstFSEventStreamRef) -> dev_t

8.FSEventStreamGetLatestEventId

获取流的sinceWhen属性。在接收到事件时(在调用客户端回调之前),此属性将被更新为事件中提到的最高编号的事件ID。

func FSEventStreamGetLatestEventId(_ streamRef: ConstFSEventStreamRef) -> FSEventStreamEventId

9.FSEventStreamInvalidate(_:)

使FSEventStreamRef无效,就像CFRunLoopSourceInvalidate()对CFRunLoopSourceRef所做的那样。它将从任何已调度的运行循环或调度队列中取消调度。

注意:FSEventStreamInvalidate()只能在调用FSEventStreamScheduleWithRunLoop或者FSEventStreamSetDispatchQueue()之后

10.FSEventStreamRelease(_:)

减少流的引用计数。refcount最初是1,FSEventStreamRetain()递增。如果引用计数达到零,则释放流。

func FSEventStreamRelease(_ streamRef: FSEventStreamRef)

11.FSEventStreamRetain(_:)

递增流的引用计数

func FSEventStreamRetain(_ streamRef: FSEventStreamRef)

12.FSEventStreamScheduleWithRunLoop(::_:)

这个函数在指定的运行循环上调度流,就像CFRunLoopAddSource()对CFRunLoopSourceRef所做的那样。调用方负责确保流至少在一个运行循环中被调度,并且至少在调度流的运行循环中被运行。如果要开始接收流上的事件,则调用FSEventStreamStart()。
要从已调度的运行循环中删除流,请调用FSEventStreamUnscheduleFromRunLoop或FSEventStreamInvalidate()

func FSEventStreamScheduleWithRunLoop(_ streamRef: FSEventStreamRef, _ runLoop: CFRunLoop, _ runLoopMode: CFString)

13.FSEventStreamSetDispatchQueue

此函数在指定的队列上调度流。调用方负责确保流被调度到调度队列上,并且队列已经启动。如果在队列上调度流有问题,则在尝试启动流时将返回错误。

要开始接收流上的事件,调用FSEventStreamStart()。

要从调度流的指定队列中删除流,则调用FSEventStreamInvalidate()

注意:不要设置队列为NULL,如果为NULL则不能调用FSEventStreamInvalidatee()去使流无效。否则会发生错误!

func FSEventStreamSetDispatchQueue(_ streamRef: FSEventStreamRef, _ q: DispatchQueue?)

14.FSEventStreamSetExclusionPaths(::)

设置从EventStream中过滤的目录。最多可以指定8个目录。

func FSEventStreamSetExclusionPaths(_ streamRef: FSEventStreamRef, _ pathsToExclude: CFArray) -> Bool

15.FSEventStreamShow(_:)

将所提供流的描述打印到标准错误。仅供调试。

func FSEventStreamShow(_ streamRef: ConstFSEventStreamRef)

示例:

(lldb) po FSEventStreamShow(self.syncEventStream)
FSEventStreamRef @ 0x129004e20:
   allocator = 0x1f1cd88c0
   callback = 0x10411ea68
   f2d_private_port = 0x13903
   context = {0, 0x6000035e6300, 0x0, 0x0, 0x0}
   numPathsToWatch = 1
   pathsToWatch = 0x6000019e0080
        pathsToWatch[0] = '/'
   numPathsToExclude = 0
   latestEventId = 6270384
   latency = 1000000000 (microseconds)
   flags = 0x00000011
   runLoop = 0x6000027e4200
   runLoopMode = 0x1f1ce52a8
(lldb) 

16.FSEventStreamStart(_:)

尝试向FS Events服务注册,以接收流中每个参数的事件。
只有当流在至少一个运行循环上被调度时(FSEventStreamScheduleWithRunLoop),才可以调用FSEventStreamStart()。
一旦启动,流可以通过FSEventStreamStop()停止。

func FSEventStreamStart(_ streamRef: FSEventStreamRef) -> Bool

17.FSEventStreamStop(_:)

取消向FS Events服务注册。当流停止时,客户端回调将不会被调用。
只有在流已经启动时(调用FSEventStreamStart启动),才可以调用FSEventStreamStop。
一旦停止,流可以通过FSEventStreamStart重新启动,此时它将继续接收从它停止的地方("sinceWhen")接收的事件。

func FSEventStreamStop(_ streamRef: FSEventStreamRef)

18.FSEventStreamUnscheduleFromRunLoop

这个函数从指定的运行循环中删除流,就像CFRunLoopRemoveSource()对CFRunLoopSourceRef所做的那样。

func FSEventStreamUnscheduleFromRunLoop(_ streamRef: FSEventStreamRef, _ runLoop: CFRunLoop, _ runLoopMode: CFString)

19.FSEventsCopyUUIDForDevice(_:)

获取与设备关联的UUID.如果为NULL(例如,在只读设备上)。UUID(非null)唯一标识给定的FSEvents流。如果这个(非null) UUID与上一次运行中存储的UUID不同,那么事件流也不同(例如,因为清除了FSEvents,因为磁盘被擦除,或者因为事件ID计数器被包装回零)。
一个NULL返回值表明“历史的”事件是不可用的,也就是说,你不应该提供一个“sinceWhen”值给FSEventStreamCreate(),除了kFSEventStreamEventIdSinceNow。
也就是在第一次初始化FSEventStreamCreate的时候,应该sinceWhen传kFSEventStreamEventIdSinceNow,之后的值就传存储在本地的sinceWhen(钥匙串或者偏好设置)

func FSEventsCopyUUIDForDevice(_ dev: dev_t) -> CFUUID?

20.FSEventsGetCurrentEventId()

获取最近生成的事件ID,在系统范围内(不只是一个流)。当它返回到应用程序时,甚至可能已经生成了更新的事件。
如果currentId = 上一次id + 1,文件可能被重命名或者移动了。

func FSEventsGetCurrentEventId() -> FSEventStreamEventId

21.FSEventsGetLastEventIdForDeviceBeforeTime(::)

获取给定设备在给定时间之前返回的最后一个事件ID。这是一种保守的做法,如果您随后使用返回的事件ID作为FSEventStreamCreateRelativeToDevice()的sinceWhen参数,那么您将不会错过自那时以来发生的任何事件。另一方面,您可能会收到一些(无害的)额外事件。

注意:有一些事情可能会导致这个不准确。例如,有人可能会更改系统的时钟(向后或向前)。或者,在没有完全同步时钟的情况下,外部驱动器也可以用于不同的系统。

22.FSEventsPurgeEventsForDeviceUpToEventId(::)

从服务维护的每卷持久化数据库中清除旧事件。只能由root用户调用。

func FSEventsPurgeEventsForDeviceUpToEventId(_ dev: dev_t, _ eventId: FSEventStreamEventId) -> Bool

23.FSEventStreamCreateFlags

传递给FSEventStreamCreatee…()函数,表示正在创建的流的行为标志

23.1 kFSEventStreamCreateFlagNone = 0x00000000 默认值

23.2 kFSEventStreamCreateFlagUseCFTypes = 0x00000001

框架将使用CF类型而不是原始的C类型(例如,CFStringRefs的CFArrayRef,而不是原始C字符串指针的原始C数组)调用你的回调函数

23.3 kFSEventStreamCreateFlagNoDefer = 0x00000002

重置创建FS流对象的延迟计时器,使之无效。

如果你指定了这个标志,并且从最后一个事件开始超过了延迟秒,你的应用程序将立即接收到这个事件。事件的传递将重置延迟计时器,任何后续事件都将在延迟数秒过后传递。这个标志对于那些交互性强、希望对变化立即做出反应、但避免在变化频繁发生时被通知淹没的应用很有用。

如果不指定此标志,则在一段时间无事件之后发生事件时,将启动延迟计时器。在下一个延迟秒内发生的任何事件都将作为一个组交付(包括第一个事件)。事件组的传递将重置延迟计时器,任何进一步的事件将在延迟秒之后传递。这是默认行为,更适合于后台、守护程序或批处理应用程序。

23.4 kFSEventStreamCreateFlagWatchRoot = 0x00000004

请求沿着路径向您正在观察的路径发出变更通知。例如,使用这个标志,如果你监听的文件路径为“/foo/bar”并将其重命名为“/foo/bar.old”。,你会收到一个RootChanged事件。如果目录"/foo"被重命名,也是同样的情况。您接收到的事件是一个特殊事件:事件的路径是您指定的原始路径,设置了标志kFSEventStreamEventFlagRootChanged并且事件ID为零。
RootChanged事件在指示您应该重新扫描特定的层次结构时很有用,因为它已经完全更改了(而不是其中的内容在更改)
如果希望跟踪目录的当前位置,最好在创建流之前打开目录,以便为它提供一个文件描述符,并可以发出F_GETPATH fcntl()来查找当前路径。

23.5 kFSEventStreamCreateFlagIgnoreSelf __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_6_0) = 0x00000008

不要发送由当前进程触发的事件。
这对于减少发送的事件量很有用。只有当您的进程可能修改正在监视的路径下的文件系统层次结构时,它才有用。

注意:这对历史事件没有影响,即那些在HisoryDone哨兵事件之前交付的事件。而且,这并不适用于RootChanged事件,因为WatchRoot特性使用了一种独立的机制,无法提供有关所负责进程的信息

23.6 kFSEventStreamCreateFlagFileEvents __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_6_0) = 0x00000010

请求文件级别通知。你的流将接收关于你正在观察的层次结构中的单个文件的事件,而不仅仅是接收目录级别的通知。使用此标志时要小心,因为它将生成比没有它时多得多的事件。

23.7 kFSEventStreamCreateFlagMarkSelf __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0) = 0x00000020

用“OwnEvent”标记当前进程触发的事件。只有当您的进程可能修改正在监视的路径下的文件系统层次结构,并且您希望知道您的进程触发了哪些事件时,这才有用。

注意:这对历史事件没有影响,即那些在HistoryDone哨兵事件之前交付的事件。

23.8 kFSEventStreamCreateFlagUseExtendedData __OSX_AVAILABLE_STARTING(__MAC_10_13, __IPHONE_11_0) = 0x00000040

需要kFSEventStreamCreateFlagUseCFTypes,并指示框架使用CF类型调用你的回调函数,但不是传递CFArrayRef的CFArrayRef,而是传递CFDictionaryRefs的CFArrayRef。每个字典将包含事件路径和可能的其他关于事件的“扩展数据.

24.FSEventStreamEventFlags

可以传递给您的 FSEventStreamCallback函数的标志。重要的是要注意,事件标志只是关于在该路径上发生的操作类型的提示。

24.1 kFSEventStreamEventFlagNone = 0x00000000

此事件中提供的特定路径处的目录发生了一些更改

24.2 kFSEventStreamEventFlagMustScanSubDirs = 0x00000001

您的应用程序不仅必须重新扫描事件中给定的目录,还必须递归地重新扫描其所有子目录。如果出现事件分层合并的问题,就会发生这种情况。例如,/Users/jsmith/Music 中的一个事件和 /Users/jsmith/Pictures中的一个事件可能会合并为一个设置了此标志且 path=/Users/jsmith的事件。如果设置了此标志,您可以通过检查信息标志kFSEventStreamEventFlagUserDropped 或 kFSEventStreamEventFlagKernelDropped.

24.3 kFSEventStreamEventFlagUserDropped = 0x00000002

除了 kFSEventStreamEventFlagMustScanSubDirs 标志外,还可以设置 kFSEventStreamEventFlagUserDropped 或 kFSEventStreamEventFlagKernelDropped 标志,以指示在缓冲事件时出现问题(特定标志集指示问题发生的位置)并且客户端必须对任何目录进行全面扫描(和它们的子目录,递归地)被这个流监视。如果您要求使用此流监视多个路径,那么您将收到有关所有路径的通知。您的代码只需要检查 kFSEventStreamEventFlagMustScanSubDirs标志;这些标志(如果存在)仅提供帮助您诊断问题的信息。

24.4 kFSEventStreamEventFlagKernelDropped = 0x00000004

如果设置了 kFSEventStreamEventFlagEventIdsWrapped,这意味着 64 位事件 ID 计数器环绕。因此,先前发布的事件 ID 不再是 FSEventStreamCreate...() 函数的 sinceWhen 参数的有效参数。

24.5 kFSEventStreamEventFlagEventIdsWrapped = 0x00000008

如果设置了 kFSEventStreamEventFlagEventIdsWrapped,这意味着 64 位事件 ID 计数器环绕。因此,先前发布的事件 ID 不再是 FSEventStreamCreate...() 函数的 sinceWhen 参数的有效参数。

24.6 kFSEventStreamEventFlagHistoryDone = 0x00000010

表示发送的标记事件以标记“历史”事件的结束由于在创建此事件流的 FSEventStreamCreate...() 调用中指定了一个 sinceWhen 值而发送。(如果 kFSEventStreamEventIdSinceNow被传递给sinceWhen,它不会被发送。)在使用之前发生的所有“历史”事件调用客户端的回调之后,将使用设置了kFSEventStreamEventFlagHistoryDone 标志的事件调用客户端的回调。客户端应忽略此回调中提供的路径。

24.7 kFSEventStreamEventFlagRootChanged = 0x00000020

表示当您要求观看的目录之一的路径上的目录之一发生更改时发送的特殊事件。设置此标志后,事件 ID 为零,并且路径对应于您要求观看的路径之一(特别是更改的路径)。该路径可能不再存在,因为它或其父路径之一已被删除或重命名。只有当您在创建流时将标志 kFSEventStreamCreateFlagWatchRoot 传递给 FSEventStreamCreate...() 时,才会发送设置了此标志的事件。

24.8 c = 0x00000040

表示在其中一个路径下安装卷时发送的特殊事件被监控。事件中的路径是新安装的卷的路径。对于内核中的每个卷挂载事件,您都会收到这些通知之一(独立于DiskArbitration)。请注意,新安装的卷可能包含任意大的目录层次结构。避免诸如触发非本地文件系统的递归扫描之类的陷阱,您可以通过检查 statfs() 返回的 f_flags 中是否缺少 MNT_LOCAL 标志来检测。还请注意为不应由用户界面元素显示的卷设置的 MNT_DONTBROWSE 标志。

24.9 kFSEventStreamEventFlagUnmount = 0x00000080

表示在被监视的路径之一下卸载卷时发送的特殊事件。事件中的路径是卸载卷的目录的路径。对于内核中的每个卷卸载事件,您都会收到这些通知之一。这不能替代 DiskArbitration 框架提供的通知;您只会在卸载发生后收到通知。请注意,卸载卷可能会发现任意大的目录层次结构,尽管 Mac OS X 永远不会这样做。

24.10 kFSEventStreamEventFlagItemCreated __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_6_0) = 0x00000100

在此事件中提供的特定路径上创建了文件系统对象。(只有在创建流时指定 FileEvents 标志时才会设置此标志。)

24.11 kFSEventStreamEventFlagItemRemoved __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_6_0) = 0x00000200

在此事件中提供的特定路径中删除了文件系统对象。(只有在创建流时指定 FileEvents 标志时才会设置此标志。)

24.12 kFSEventStreamEventFlagItemInodeMetaMod __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_6_0) = 0x00000400

此事件中提供的特定路径上的文件系统对象已修改其元数据。(只有在创建流时指定 FileEvents 标志时才会设置此标志。)

24.13 kFSEventStreamEventFlagItemRenamed __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_6_0) = 0x00000800

在此事件中提供的特定路径中重命名了文件系统对象。(只有在创建流时指定 FileEvents 标志时才会设置此标志。)

24.14 kFSEventStreamEventFlagItemModified __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_6_0) = 0x00001000

此事件中提供的特定路径上的文件系统对象已修改其数据。(只有在创建流时指定 FileEvents 标志时才会设置此标志。)

24.15 kFSEventStreamEventFlagItemFinderInfoMod __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_6_0) = 0x00002000

此事件中提供的特定路径上的文件系统对象已修改其 FinderInfo 数据。(只有在创建流时指定 FileEvents 标志时才会设置此标志。)

24.16 kFSEventStreamEventFlagItemChangeOwner __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_6_0) = 0x00004000

此事件中提供的特定路径上的文件系统对象的所有权已更改。(只有在创建流时指定 FileEvents 标志时才会设置此标志。)

24.17 kFSEventStreamEventFlagItemXattrMod __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_6_0) = 0x00008000

此事件中提供的特定路径上的文件系统对象已修改其扩展属性。(仅当您在创建流时指定 FileEvents 标志时才会设置此标志。)

24.18 kFSEventStreamEventFlagItemIsFile __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_6_0) = 0x00010000

此事件中提供的特定路径上的文件系统对象是常规文件。(只有在创建流时指定 FileEvents 标志时才会设置此标志。)

24.19 kFSEventStreamEventFlagItemIsDir __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_6_0) = 0x00020000

此事件中提供的特定路径上的文件系统对象是一个目录。(只有在创建流时指定 FileEvents 标志时才会设置此标志。)

24.20 kFSEventStreamEventFlagItemIsSymlink __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_6_0) = 0x00040000

此事件中提供的特定路径上的文件系统对象是符号链接。(仅当您在创建流时指定 FileEvents 标志时才会设置此标志。)

24.21 kFSEventStreamEventFlagOwnEvent __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0) = 0x00080000

表示事件是由当前进程触发的。(只有在创建流时指定了 MarkSelf 标志时才会设置此标志。)

24.22 kFSEventStreamEventFlagItemIsHardlink __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_9_0) = 0x00100000

表示此事件中提供的指定路径上的对象是硬链接。(只有在创建流时指定了 FileEvents 标志时才会设置此标志。)

24.23 kFSEventStreamEventFlagItemIsLastHardlink __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_9_0) = 0x00200000

表示此事件中提供的特定路径上的对象是最后一个硬链接。(仅当您在创建流时指定 FileEvents 标志时才会设置此标志。)

24.24 kFSEventStreamEventFlagItemCloned __OSX_AVAILABLE_STARTING(__MAC_10_13, __IPHONE_11_0) = 0x00400000

此事件中提供或提供的特定路径上的文件系统对象是克隆的. (只有在创建流时指定 FileEvents 标志时才会设置此标志。)

25.FSEventStreamCallback

这是客户端在创建新流时提供的回调函数的类型。当事件发生时,服务根据创建流时指定的参数从客户端运行循环调用此回调。
streamRef:事件发生的流。

clientCallBackInfo:创建此流时在上下文中提供的信息字段。

numEvents:在这个回调中报告的事件数。每个数组(eventPaths, eventFlags, evententids)都有这么多元素。

eventPaths:事件发生所在目录的路径数组。这个参数的类型取决于传递给FSEventStreamCreate…()的标志。如果设置了kFSEventStreamCreateFlagUseCFTypes,那么这将是一个包含CFStringRef对象的CFArrayRef(每个CFStringCreateWithFileSystemRepresentation())。所有权遵循Get规则,它们将在你的回调返回后由框架释放。如果kFSEventStreamCreateFlagUseCFTypes没有设置,那么框架将传递给你的回调一个原始C字符串的原始C数组,在你的回调返回后,框架将被释放。

eventFlags:对应于eventPaths参数中的路径的行为标识(创建、删除、重命名等)数组。如果没有设置标志,则在此事件中提供的特定路径上的目录中有一些更改。

eventIds:一个FSEventStreamEventIds数组,对应于eventPaths参数中的路径。
每个事件ID来自在eventPaths参数中命名的相应目录中报告的最近的事件。事件id都来自一个全局源。它们保证总是在增加,通常是跳跃式增长,甚至跨越系统重新启动和将驱动器从一台机器移动到另一台机器。就在调用回调之前,你的流被更新,以便调用访问器FSEventStreamGetLatestEventId时将返回在eventIds参数中传递的最大值;如果你要在回调之后停止处理这个流中的事件,并在稍后从新创建的FSEventStream中继续处理它们,这是你要传递给fsevenstreamcreate…()函数的sinceWhen参数的值。最好把id存在本地。

typealias FSEventStreamCallback = (ConstFSEventStreamRef, UnsafeMutableRawPointer?, Int, UnsafeMutableRawPointer, UnsafePointer<FSEventStreamEventFlags>, UnsafePointer<FSEventStreamEventId>) -> Void

应用

可以参阅: MacOS 开发 - FSEventStream(文件系统改变事件监控)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352

推荐阅读更多精彩内容