我正在使用FSEvents API来获取我正在跟踪的本地目录中的更改通知。
是否可以使用FSEvents或其他任何内容获取已监视目录已移至磁盘上其他位置的通知?
更新
这是我到目前为止的代码,我现在正尝试使用带有FSEventStreamCreate的kFSEventStreamCreateFlagWatchRoot标志来获取root更改通知,到目前为止还没有成功。
- (void)registerForFileSystemNotifications {
NSString *watchedDirectoryPath = [[NSUserDefaults standardUserDefaults] valueForKey:kMyWatchedDirectoryPathKey];
self.watchedDirectoryFileDescriptor = open([watchedDirectoryPath cStringUsingEncoding:NSUTF8StringEncoding], O_RDONLY);
NSArray *paths = [NSArray arrayWithObject:watchedDirectoryPath];
void *appController = (void *)self;
FSEventStreamContext context = {0, appController, NULL, NULL, NULL};
FSEventStreamRef streamRef = FSEventStreamCreate(NULL,
&fsevents_callback,
&context,
(CFArrayRef) paths,
kFSEventStreamEventIdSinceNow,
(CFTimeInterval)2.0,
kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagWatchRoot);
FSEventStreamScheduleWithRunLoop(streamRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
FSEventStreamStart(streamRef);
}
void fsevents_callback(ConstFSEventStreamRef streamRef,
void *userData,
size_t numumberOfEvents,
void *eventPaths,
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[]) {
MyAppController *appController = (MyAppController *)userData;
char *newPath = calloc(4096, sizeof(char));
int pathIntPointer = (int)newPath;
int length = fcntl(appController.watchedDirectoryFileDescriptor, F_GETPATH, pathIntPointer);
NSString *newPathString = [[NSString alloc] initWithBytes:newPath length:(NSUInteger)length encoding:NSUTF8StringEncoding];
NSLog(@"newPathString: %@", newPathString); // empty
}
答案 0 :(得分:6)
是。将kFSEventStreamCreateFlagWatchRoot
作为FSEventStreamCreate
的最后一个参数传递,如果目录已移动或重命名,您将收到通知。来自docs:
请求通知您正在观看的路径的路径更改。例如,使用此标志,如果您观看“/ foo / bar”并将其重命名为“/foo/bar.old”,您将收到RootChanged事件。如果重命名目录“/ foo”,情况也是如此。您收到的事件是一个特殊事件:事件的路径是您指定的原始路径,标志kFSEventStreamEventFlagRootChanged已设置且事件ID为零。 RootChanged事件可用于指示您应该重新扫描特定层次结构,因为它完全更改(而不是更改内部的内容)。如果要跟踪目录的当前位置,最好在创建流之前打开目录,以便为其创建文件描述符,并发出F_GETPATH fcntl()以查找当前路径。
编辑:添加fcntl示例
cocoadev的例子表明作者对指针有点缺乏经验。 pathIntPointer不仅是不必要的,它也是问题的原因。从fnctl检查返回码的错误会抓住它。这是您的回调的修订版本:
void fsevents_callback(ConstFSEventStreamRef streamRef,
void *userData,
size_t numumberOfEvents,
void *eventPaths,
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[]) {
MyAppController *appController = (MyAppController *)userData;
char newPath[ MAXPATHLEN ];
int rc;
rc = fcntl( appController.watchedDirectoryFileDescriptor, F_GETPATH, newPath );
if ( rc == -1 ) {
perror( "fnctl F_GETPATH" );
return;
}
NSString *newPathString = [[NSString alloc] initWithUTF8String: newPath ];
NSLog(@"newPathString: %@", newPathString);
[ newPathString release ];
}