2011-04-27 70 views
8

我正在使用FSEvents API來獲取我要跟蹤的本地目錄中的更改通知。是否可以使用FSEvents來獲取文件夾已被移動的通知?

是否有可能使用FSEvent或其他方式獲得通知,指出已監視的目錄已被移動到磁盤上的另一個位置?

更新:

這裏是我到目前爲止的代碼,我現在嘗試使用kFSEventStreamCreateFlagWatchRoot標誌與FSEventStreamCreate得到根本改變的通知,至今沒有成功。

- (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 
} 

回答

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 ]; 
} 
+0

謝謝!我正在嘗試這個,但迄今沒有任何運氣。我已將現有的代碼添加到問題中。我能找到的唯一使用F_GETPATH的例子是http://www.cocoadev.com/index.pl?DescriptorToPath。感謝您的幫助! – 2011-04-28 03:30:38

+0

太棒了。謝謝 :) – 2011-04-28 19:24:01

相關問題