2010-01-28 18 views
8

Sono in ascolto per le modifiche della directory e del disco in un progetto Cocoa utilizzando FSEvents. Ho bisogno di ottenere eventi quando una cartella principale viene rinominata o cancellata. Quindi, ho passato kFSEventStreamCreateFlagWatchRoot durante la creazione di FSEventStream. Ma anche se cancello o rinominare la cartella radice non sto ottenendo il corrispondente FSEventStreamEventFlags. Qualche idea su quale potrebbe essere il problema. Sto ascoltando le modifiche in un dispositivo USB montato. Ho usato sia FSEventStreamCreate e FSEventStreamCreateRelativeToDevice. Una cosa che le comunicazioni è quando provo con FSEventStreamCreate ricevo il seguente messaggio di errore durante la creazione FSEventStream:Come ascoltare le modifiche al file system MAC - kFSEventStreamCreateFlagWatchRoot

(CarbonCore.framework) FSEventStreamCreate: watch_all_parents:
errore nel tentativo di aggiungere kqueue per fd 7 (/Volumes/NO NAME; Operazione non supportata)

ma con FSEventStreamCreateRelativeToDevice non ci sono errori, ma ancora non ottenere kFSEventStreamEventFlagRootChanged in bandiere di eventi. Inoltre, durante la creazione utilizzando FSEventStreamCreateRelativeToDevice apple dire se voglio ascoltare le modifiche al percorso radice passare la stringa emty "". Ma non sono in grado di ascoltare le modifiche al percorso radice passando una stringa vuota. Ma quando passo "/" funziona. Ma anche per "/" non ho alcun diritto FSEventStreamEventFlags. Sto incollando il codice qui: torna

-(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); 


} 

chiamata di funzione:

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]]); 
    }  
} 

Grazie mille in anticipo.

+0

Non sono sicuro di cosa non ci sia perché non ho mai utilizzato FSEvents. Detto questo, sembra che quello che stai cercando di fare potrebbe essere fatto meglio usando il framework DiskArbitration. –

risposta

3

Ho avuto lo stesso problema e penso che ho capito. Apparentemente kFSEventStreamCreateFlagWatchRoot viene semplicemente arrestato quando si utilizza FSEventStreamCreateRelativeToDevice. Devi usare FSEventStreamCreate. Dal momento che la precedente forma è preferibile se si fa affidamento su ID eventi storici, potrebbe essere necessario creare 2 flussi. Inoltre, tieni presente che sembra che non ti venga inviato kEventFlagChangedRoot se la tua app non è in esecuzione, quindi all'avvio dovrai impostare la directory.

3

Penso che la modifica del nome del volume non venga conteggiata come una modifica del file system riportato da FSEvents. Ricorda, il nome del volume stesso non esiste realmente come una voce del file system. Quelle sotto /Volumes sono preparate dal sistema operativo.

È invece coperto da Disk Arbitration.

Segue un breve codice di esempio. In primo luogo, definire il callback

#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); 
} 

e quindi installare il gestore come questo

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

HI Grazie per la risposta. Ma io sono più alla ricerca di una soluzione con FSEVENTS perché ciò che realmente mi infastidisce è che, anche se fornisco il percorso root "/" o qualsiasi sottodirectory e poi lo elimini o lo rinomini, non ricevo i flag di evento corretti nella richiamata. Ho incollato il codice nella domanda. Un'altra domanda, dove ottengo il riferimento completo di Disk Arbiteration perché non so quali chiavi dovrei guardare o guardare ecc.O inshort, dove si trova la spiegazione di kDADiskDescriptionVolumePathKey o kDADiskDescriptionWatchVolumeName. – wantro

+0

Le chiavi sono disponibili su http://developer.apple.com/it/mac/library/documentation/Darwin/Reference/DiscArbitrationFramework/index.html ... Beh, sai che c'è una casella di ricerca nel sito Web di ADC, a destra ? Hai cercato la costante lì? Lasciami pensare alla tua prima domanda. – Yuji

+0

Ho copiato e incollato il codice e ha funzionato sulla mia macchina (10.6.2). Potresti postare la tua routine di callback e come stai controllando i flag di evento restituiti? – Yuji

Problemi correlati