You can also use GCD dispatch sources to observe filesystem events.
An advantage over the (older) FSEvents API is, that dispatch sources notify via block-based handlers.
You can also specify a mask for the events that you are interested in (e.g. DISPATCH_VNODE_DELETE
|DISPATCH_VNODE_RENAME
for renames and deletions)
NSURL* url = [NSURL fileURLWithPath:[@"~/Desktop/test.txt" stringByExpandingTildeInPath]];
dispatch_queue_t observerQueue = dispatch_queue_create("filesystem-observer-queue", 0);
int fileDescriptor = open([url fileSystemRepresentation], O_EVTONLY);
dispatch_source_vnode_flags_t eventMask = DISPATCH_VNODE_DELETE|DISPATCH_VNODE_RENAME;
dispatch_source_t fileSystemSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fileDescriptor, eventMask, observerQueue);
dispatch_source_set_event_handler(fileSystemSource, ^{
dispatch_source_vnode_flags_t eventSourceFlag = dispatch_source_get_data(fileSystemSource);
if(eventSourceFlag & DISPATCH_VNODE_DELETE)
{
NSLog(@"delete");
dispatch_source_cancel(fileSystemSource);
}
else if(eventSourceFlag & DISPATCH_VNODE_RENAME)
{
NSLog(@"rename");
}
NSLog(@"Change at %@ of type %lu", url, eventSourceFlag);
});
dispatch_source_set_cancel_handler(fileSystemSource, ^{
close(fileDescriptor);
});
dispatch_resume(fileSystemSource);
Some notes:
- The above code just shows the general idea. It does not try to cover all edge cases.
- When you observe a directory, you only get one notification that something changed, but no information about the affected file(s) or the change type.
- DISPATCH_VNODE_DELETE means true deletion (e.g. not the Finders move to trash)