是否可以使用FSEvents获取文件夹已被移动的通知?

Joe*_*ppo 8 cocoa fsevents

我正在使用FSEvents API来获取我正在跟踪的本地目录中的更改通知.

是否可以使用FSEvents或其他任何内容获得已监视目录已移至磁盘上其他位置的通知?

更新:

这是我到目前为止的代码,我现在正在尝试使用FSEventStreamCreate的kFSEventStreamCreateFlagWatchRoot标志来获取根更改通知,到目前为止还没有成功.

- (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
}
Run Code Online (Sandbox Code Playgroud)

mor*_*ion 6

是.通过kFSEventStreamCreateFlagWatchRoot作为最后一个参数FSEventStreamCreate,你会如果被通知该目录的移动或重命名.来自文档:

请求通知您正在观看的路径的路径更改通知.例如,使用此标志,如果您观看"/ 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 ];
}
Run Code Online (Sandbox Code Playgroud)