2010-01-28 74 views
8

我正在使用FSEvents偵聽Cocoa項目中的目錄和磁盤更改。當根文件夾被重命名或刪除時,我需要獲取事件。所以,我通過kFSEventStreamCreateFlagWatchRoot,同時創建了FSEventStream。但即使我刪除或重命名根文件夾我沒有得到相應的FSEventStreamEventFlags。任何想法可能是什麼問題。我正在監聽USB安裝設備的更改。我同時使用了FSEventStreamCreateFSEventStreamCreateRelativeToDevice。有一件事我通知是當我嘗試用FSEventStreamCreate我收到以下錯誤消息在創建FSEventStream如何監聽文件系統更改MAC - kFSEventStreamCreateFlagWatchRoot

CarbonCore.frameworkFSEventStreamCreatewatch_all_parents
錯誤嘗試添加的kqueue爲fd 7/Volumes/NO NAME;不支持操作)

但與FSEventStreamCreateRelativeToDevice有沒有錯誤,但仍沒有得到kFSEventStreamEventFlagRootChanged事件標誌。此外,雖然創建使用FSEventStreamCreateRelativeToDevice蘋果說,如果我想聽根路徑變化通過emty字符串""。但是我不能通過傳遞空字符串來偵聽根路徑變化。但是,當我通過"/"它的作品。但即使對於"/"我也沒有得到任何正確的FSEventStreamEventFlags。我在這裏粘貼代碼:

-(void) subscribeFileSystemChanges:(NSString*) path 
{ 
    PRINT_FUNCTION_BEGIN; 

    // if already subscribed then unsubscribe 
    if (stream) 
    { 
     FSEventStreamStop(stream); 
     FSEventStreamInvalidate(stream); /* will remove from runloop */ 
     FSEventStreamRelease(stream); 
    } 

    FSEventStreamContext cntxt = {0}; 
    cntxt.info = self; 

    CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void**)&path, 1, NULL); 


    stream = FSEventStreamCreate(NULL, &feCallback, &cntxt, 
           pathsToWatch, kFSEventStreamEventIdSinceNow, 1, 
           kFSEventStreamCreateFlagWatchRoot); 


    FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), 
            kCFRunLoopDefaultMode); 

    FSEventStreamStart(stream); 


} 

回調函數:

static void feCallback(ConstFSEventStreamRef streamRef, void* pClientCallBackInfo, 
         size_t numEvents, void* pEventPaths, const FSEventStreamEventFlags eventFlags[], 
         const FSEventStreamEventId eventIds[]) 

{ 
char** ppPaths = (char**)pEventPaths; int i; 

    for (i = 0; i < numEvents; i++) 
    { 
     NSLog(@"Event Flags %lu Event Id %llu", eventFlags[i], eventIds[i]); 
     NSLog(@"Path changed: %@", 
       [NSString stringWithUTF8String:ppPaths[i]]); 
    }  
} 

非常感謝提前。

+0

我不知道那裏有什麼問題,因爲我從來沒有使用過FSEvents。話雖如此,這聽起來像你試圖做的可能會更好地使用DiskArbitration框架完成。 – 2010-01-28 16:02:06

回答

3

我有同樣的問題,我想我想通了。當使用FSEventStreamCreateRelativeToDevice時,顯然kFSEventStreamCreateFlagWatchRoot只是簡單的破壞。你必須使用FSEventStreamCreate。由於如果您依賴歷史事件id,前一種形式更可取,因此您可能需要創建2個流。另外,請注意,如果您的應用沒有運行,您似乎沒有收到kEventFlagChangedRoot,因此您需要在啓動時統計目錄。

3

我認爲卷名的變化不會被視爲由FSEvents報告的文件系統的變化。請記住,卷名本身並不真正作爲文件系統條目存在。操作系統對/Volumes下的那些進行了編譯。

而是由Disk Arbitration覆蓋。

下面是一個簡短的示例代碼。首先,定義回調

#import <DiskArbitration/DiskArbitration.h> 
void callBack(DADiskRef disk,CFArrayRef keys,void *context) 
{ 
    CFDictionaryRef dict=DADiskCopyDescription(disk); 
    NSString*mountPoint=[(NSDictionary*)dict objectForKey:(NSString*)kDADiskDescriptionVolumePathKey]; 
    NSLog(@"disk at %@:",mountPoint); 
    for(NSString*key in (NSArray*)keys){ 
    NSLog(@"key %@ changed: %@",key,[(NSDictionary*)dict objectForKey:key]);  
    } 
    CFRelease(dict); 
} 

,然後安裝處理器這樣

DASessionRef session=DASessionCreate(NULL); 
DARegisterDiskDescriptionChangedCallback(session, NULL, NULL, callBack, NULL); 
DASessionScheduleWithRunLoop(session, [[NSRunLoop currentRunLoop] getCFRunLoop], kCFRunLoopCommonModes); 
+0

嗨,感謝您的回答。但我更想用FSEVENTS尋求一個解決方案,因爲真正困擾我的是,即使我給根路徑「/」或任何子目錄,然後刪除或重命名它,我在回調中沒有得到適當的事件標誌。我在這個問題上粘貼了代碼。 還有一個問題,我在哪裏可以獲得磁盤仲裁的完整參考,因爲我不知道應該查看或觀看哪些密鑰等。或inshort,你在哪裏解釋kDADiskDescriptionVolumePathKey或kDADiskDescriptionWatchVolumeName的解釋。 – wantro 2010-01-29 00:56:11

+0

可以在http://developer.apple.com/mac/library/documentation/Darwin/Reference/DiscArbitrationFramework/index.html找到這些密鑰......呃,你知道ADC網站上有一個搜索框,右邊?你在那裏搜索常數嗎?讓我想想你的第一個問題。 – Yuji 2010-01-29 03:26:26

+0

我複製並粘貼您的代碼,並在我的機器上運行(10.6.2)。你可以發佈你的回調例程,以及你如何檢查返回的事件標誌? – Yuji 2010-01-29 03:46:16