2011-09-04 23 views
13

Sto provando a utilizzare FSEvents per rilevare quando i file sono stati aggiunti/rimossi da una cartella specifica. Per il momento, ho implementato un semplice wrapper su FSEvents, e funziona perfettamente: ottengo tutti gli eventi.rinominare/eliminare il file di tracciamento con FSEvents su Lion

ma il problema che ho ora è che quando rinomina un file nel Finder, prendo 2 eventi distinti: il primo di tipo "rinominato" con il vecchio nome del file, e un altro con "rinominato" e la nuovo nome file. Gli ID evento sono diversi tra le due chiamate.

Quindi, come faccio a sapere quale evento "rinominato" contiene il vecchio nome e quale evento contiene quello precedente ?? Ho provato a cercare nella documentazione, ma sfortunatamente, kFSEventStreamEventFlagItemRenamed non è documentato ... sembra nuovo in Lion.

PS: l'unico modo in cui potevo pensare era: in un evento ribattezzato, controllo la mia interfaccia utente per vedere se ho un articolo corrispondente al percorso dell'evento. In tal caso, lo contrassegno per la ridenominazione. In caso contrario, controllo se un elemento è stato contrassegnato per la ridenominazione e, in tal caso, lo rinominerò nel nuovo percorso dell'evento. Ma davvero non mi piace questa idea ...

Modifica: Ok, ho imitato qualcosa lungo la linea del mio "PS": ho notato che quando si rinomina qualcosa, gli id ​​dei 2 eventi sono consecutivi, in modo che con l'id dell'evento che contiene il nuovo nome, posso ottenere l'evento contenente il vecchio nome. Io uso semplicemente un po 'di dizione nella mia interfaccia per memorizzare id e percorsi associati nel caso di un evento "rinominato".

Ad ogni modo, ora posso prendere rinominare eventi, e anche spostare gli eventi: quando si sposta un file, si tratta di un evento "rinominato", che viene catturato dal FSEventStream ...

Ma, ho ancora un ultimo problema: eliminazione. Quando elimino qualcosa, viene spostato nel cestino: ricevo un evento "rinominato". Ma il problema è che non ricevo il secondo evento di rinomina. Solo un evento "modificato" nel file .DS_Store. Penso che questo file sia usato dal Finder per sapere quali file sono nel cestino, ecc. Quindi posso controllare la modifica di questo file e ottenere l'ultimo evento "rinominato" per rilevare che un file è stato inviato al cestino. Ma sto usando TotalFinder che usa Asepsis, che modifica il modo in cui il Finder memorizza i file .DS_Store: non ricevo più "modificato" su questo. Per sumarize: Non riesco a rilevare quando un file viene inviato al contenitore ...

Qualche idea su come posso farlo? Forse usare qualcos'altro di FSEvents per catturare solo questo evento?

risposta

13

Beh, non ho trovato la risposta perfetta alla mia domanda, ma ho trovato una soluzione che alla fine ho rimasto molto soddisfatto, così ho pensato che avrei potuto condividere ^^

Come ho detto, quando si spostano roba nel cestino, se stai guardando solo una cartella, non catturerai l'evento generato quando l'immagine viene messa nel cestino. Quindi, ho deciso di fare quanto segue: Ho una classe che crea uno stream nella cartella root ("/") in modo che possa catturare tutti gli eventi -> questo risolve il problema dei file inviati al cestino, e tutte queste cose Quindi, questa classe consente di registrare i delegati su determinati percorsi. Quindi, invece di creare molti flussi, creo un grande flusso, quindi filtri gli eventi secondo necessità e creo molti delegati.

Quindi tutto quello che devo fare ora quando voglio guardare gli eventi in una cartella speciale è la seguente:

[[FSEventsListener instance] addListener:self forPath:somePath]; 

devo solo creare un'istanza di FSEventListener all'avvio dell'applicazione, e rilasciarlo quando la l'app si ferma. E ho solo bisogno di implementare i seguenti 3 metodi che si chiamerà automaticamente:

-(void)fileWasAdded:(NSString *)file; 
-(void)fileWasRemoved:(NSString *)file; 
-(void)fileWasRenamed:(NSString *)oldFile to:(NSString *)newFile; 

Se siete interessati nel codice sorgente di questa piccola utility, è possibile controllare qui: http://blog.pcitron.fr/tools/macosx-imageviewer/ (l'utility è stata aggiunta a la versione 0.8)

L'ho sviluppato come parte di un piccolo visualizzatore di immagini per mantenere l'interfaccia utente sincronizzata con il contenuto del disco (visualizza il numero di immagini contenute in ogni directory, ecc.) Il codice sorgente è disponibile, e il l'utilità è in Utils/FSEventsListener.h/.m.

E se per caso qualcuno effettivamente scarica l'applicazione e dare un'occhiata alle fonti, se trovate qualcosa utile (miglioramento delle prestazioni/funzione, a prescindere) sentitevi liberi di cadere un commento/mail ^^

+0

molto utile, grazie per il tuo codice :) –

+0

sul tuo sito non c'è un pulsante di invio nella pagina dei contatti, dammi la tua email per favore, voglio farti qualche domanda. Grazie :) –

+0

Ho corretto il modulo di contatto sul mio sito. Non so come inviare messaggi privati ​​su StackOverflow (o anche se è possibile ^^) – Citron

4

È stanno effettivamente sollevando due problemi relativi a FSEvents e rinomina. 1. Un file viene rinominato e il nome del file vecchio e quello nuovo si trovano all'interno degli alberi delle directory monitorati. 2. Un file viene rinominato e uno dei nomi non si trova negli alberi delle directory monitorati.

Hai risolto (quasi) il primo numero. È inoltre necessario fornire alla propria applicazione un mezzo per sapere quali eventi vengono segnalati nello stesso gruppo di eventi FSEvent. Il tuo metodo per sapere che due ridenominazioni sono riportate consecutivamente funziona solo se si trovano nello stesso gruppo di eventi che vengono segnalati nello stesso periodo di latenza. Se due eventi di ridenominazione di tipo 2 si verificano uno dopo l'altro ma non si trovano nello stesso gruppo di eventi riportati nello stesso gruppo di latenza, in realtà non hanno nulla a che fare l'uno con l'altro e si penserà erroneamente che un file sia stato rinominato in un altro .

È possibile gestire il secondo tipo di ridenominazione semplicemente monitorando tutte le directory del sistema utilizzando la directory principale, ma ciò causerà numerosi eventi non necessari. È possibile determinare se una ridenominazione "parziale" è il risultato di un file che viene spostato dall'albero della directory da monitorare o nella struttura della directory da monitorare eseguendo una stat() sul file. Se stat() fallisce con un errore di 2, il file è stato spostato all'esterno della directory monitorata e può essere trattato come se fosse stato eliminato. Se stat() ha esito positivo, l'evento può essere considerato come se il file è stato creato.

+0

L'approccio stat ha una condizione di competizione: ad esempio, ci sono state mosse concatenate, quindi le statistiche su un percorso nel mezzo della sequenza falliranno. –