以下代码必须在 main.m 而不是 main.mm 中,否则无法编译。 (请参阅下面的 C++ (main.mm) 附录。)以下代码在循环中运行,观察 /Users/mike/Documents 和 /Users/mike/Downloads 中的新文件创建。 (抱歉,它不支持这些路径上的通配符——我希望它支持!)按 CTRL+C 退出运行循环。
注意在输出中,如果你下载一个文件,你会看到一个一致的标志 ID 125184。如果一个新文件从同一个文件夹复制到一个文件夹中,标志 ID 是 128256。如果一个新文件是新创建的(如从编辑器中创建的),标志 ID 为 108544。如果将现有文件拖到文件夹中,则标志 ID 为 67584。您需要不断试验 ID 以查看要捕获的事件。例如,如果编写实时病毒扫描程序,您可能希望检测通过命令行移动、拖放、剪切/粘贴或从网络下载到特定文件夹的文件。尝试各种方案和子文件夹,查看您获得的 ID,并编写捕获这些标志 ID 的代码。
#import <Foundation/Foundation.h>
void detectNewFile (
ConstFSEventStreamRef streamRef,
void *clientCallBackInfo,
size_t numEvents,
void *eventPaths,
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[])
{
int i;
char **paths = eventPaths;
printf("GOT AN EVENT!!!!\n");
for (i=0; i<numEvents; i++) {
printf("Change %llu in %s, flags %u\n", eventIds[i], paths[i], (unsigned int)eventFlags[i]);
}
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
short nPathCount = 2;
CFStringRef mypath[nPathCount];
mypath[0] = CFSTR("/Users/mike/Documents");
mypath[1] = CFSTR("/Users/mike/Downloads");
CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&mypath, nPathCount, NULL);
void *callbackInfo = NULL;
CFAbsoluteTime latency = 1.0; // seconds
FSEventStreamRef hStream = FSEventStreamCreate(NULL,
&detectNewFile,
callbackInfo,
pathsToWatch,
kFSEventStreamEventIdSinceNow,
latency,
kFSEventStreamCreateFlagFileEvents
);
FSEventStreamScheduleWithRunLoop(hStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
FSEventStreamStart(hStream);
printf("Waiting on new file creations...\n");
CFRunLoopRun(); // runs in an endless loop, only letting the callback function run
} // end autorelease pool
return 0;
}
附录
如果您需要它与 main.mm 以及 C++ 一起使用,您需要将 CoreServices.framework 库添加到构建步骤中。然后,改变这一行:
char **paths = eventPaths;
...到这一行:
char **paths = (char **)eventPaths;
然后改变这一行:
void *callbackInfo = NULL;
...到这一行:
FSEventStreamContext *callbackInfo = NULL;
然后改变这一行:
CFAbsoluteTime latency = 1.0; // seconds
...到这一行:
CFTimeInterval latency = 1.0; // seconds