2011-09-04 4 views
13

Estoy intentando usar FSEvents para detectar cuándo se agregaron/eliminaron archivos de una carpeta específica. Por el momento, implementé un contenedor simple alrededor de FSEvents, y funciona bien: recibo todos los eventos.archivo de seguimiento cambio de nombre/eliminación con FSEvents en Lion

PERO el problema que tengo ahora es que cuando cambio el nombre de un archivo en el Finder, capturo 2 eventos distintos: el primero de tipo "renombrado" con el nombre del archivo anterior, y otro con "renombrado" y el nuevo nombre de archivo. Los identificadores de eventos son diferentes entre ambas llamadas.

Entonces, ¿cómo se supone que voy a saber qué evento "renombrado" contiene el nombre anterior, y qué evento contiene el anterior? Intenté buscar en la documentación, pero desafortunadamente, kFSEventStreamEventFlagItemRenamed no está documentado ... parece nuevo en Lion.

PD: la única forma en que podía pensar era: en un evento con otro nombre, reviso mi UI para ver si tengo un elemento correspondiente a la ruta del evento. Si es así, lo señalo para cambiar el nombre. De lo contrario, verifico si un elemento fue marcado para cambiar el nombre, y si es así, entonces le cambio el nombre a la nueva ruta del evento. Pero realmente no me gusta esta idea ...

Edit: Ok, tuve algo en la línea de mi "PS": me di cuenta de que al cambiar el nombre de algo, los identificadores de los 2 eventos son consecutivos, por lo que con el id del evento que contiene el nuevo nombre, puedo obtener el evento que contiene el nombre anterior. Simplemente utilizo un pequeño dictionario en mi interfaz para almacenar identificadores y rutas asociadas en el caso de un evento "renombrado".

De todos modos, ahora puedo coger cambiar el nombre de eventos, e incluso mover eventos: cuando mueva un archivo, se trata de un evento "renombrado", que se encuentra atrapado por el FSEventStream ...

Pero, todavía tengo una última problema: eliminar Cuando elimino algo, se mueve a la papelera de reciclaje: recibo un evento "renombrado". Pero el problema es que no recibo el segundo evento de cambio de nombre. Solo un evento "modificado" en el archivo .DS_Store. Creo que el Finder usa este archivo para saber qué archivos están en el contenedor, etc. Así que pude verificar la modificación de este archivo y obtener el último evento "redenominado" para detectar que se envió un archivo al contenedor. Pero estoy usando TotalFinder que usa Asepsis, que modifica la forma en que el Buscador almacena archivos .DS_Store: ya no recibo "modificado" en esto. Para sumarizar: No puedo detectar cuando se envía un archivo al contenedor ...

¿Alguna idea de cómo puedo hacer eso? ¿Tal vez usar algo más que FSEvents para atrapar solo este evento?

Respuesta

13

Bueno, no he encontrado la respuesta perfecta a mi pregunta, pero he encontrado una solución que finalmente yo estaba muy satisfecho con, por lo que pensé que podría compartir ^^

Como ya he dicho, cuando se mueve la materia a la basura, si solo estás viendo 1 carpeta, no verás el evento generado cuando la imagen se tira a la basura. Entonces, decidí hacer lo siguiente: Tengo una clase que crea una secuencia en la carpeta raíz ("/") para que capture todos los eventos -> esto resuelve el problema de los archivos que se envían a la papelera, y todo eso. Entonces, esta clase permite registrar delegados en ciertos pathes. Entonces, en lugar de crear muchas secuencias, creo una gran transmisión, luego filmo los eventos según sea necesario y creo muchos delegados.

Así que todo lo que tengo que hacer ahora cuando quiero ver eventos en una carpeta especial

es la siguiente:

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

sólo tengo que crear una instancia de FSEventListener al inicio de la aplicación, y lo liberan cuando el la aplicación se detiene Y sólo hay que poner en práctica los siguientes 3 métodos que se llamará automáticamente:

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

Si usted está interesado en el código fuente de esta pequeña utilidad, se puede comprobar aquí: http://blog.pcitron.fr/tools/macosx-imageviewer/ (la utilidad se añadió a la versión 0.8)

Lo desarrollé como parte de un pequeño visor de imágenes para mantener la UI sincronizada con el contenido del disco (muestra el número de imágenes contenidas en cada directorio, etc.) El código fuente está disponible, y el la utilidad está en Utils/FSEventsListener.h/.m.

Y si por casualidad alguien realmente descarga la aplicación y echar un vistazo a las fuentes, si encuentras algo útil (mejora del rendimiento/función, lo que sea) no dude en pasar un comentario/mail ^^

+0

muy útil, gracias por su código :) –

+0

en su sitio no hay ningún botón de enviar en la página de contacto, denme su correo electrónico por favor, quiero hacerle algunas preguntas. Gracias :) –

+0

He arreglado el formulario de contacto en mi sitio. No sé cómo enviar un mensaje privado en StackOverflow (o incluso si es posible ^^) – Citron

4

Usted en realidad plantean dos problemas relacionados con FSEvents y cambian de nombre. 1. Se cambia el nombre de un archivo y tanto el nombre del archivo antiguo como el nuevo se encuentran dentro de los árboles del directorio que se están supervisando. 2. Se cambia el nombre de un archivo y uno de los nombres no se encuentra en los árboles de directorios que se supervisan.

Has resuelto (casi) el primer problema. También es necesario proporcionar a su aplicación un medio para saber qué eventos se están informando en el mismo grupo de eventos FSEvent. Su método de saber que dos renombrados se informan consecutivamente solo funciona si se encuentran dentro del mismo grupo de eventos que se informa dentro del mismo período de latencia. Si dos eventos de cambio de nombre de tipo 2 ocurren uno tras otro pero no están dentro del mismo grupo de eventos informados en el mismo grupo de latencia, en realidad no tienen nada que ver entre sí, y erróneamente pensarás que un archivo ha sido renombrado a otro .

Es posible manejar el segundo tipo de cambio de nombre simplemente monitoreando todos los directorios en el sistema usando la raíz, pero esto lo inundará con muchos eventos innecesarios. Puede determinar si un cambio de nombre "parcial" es el resultado de un archivo que se está moviendo fuera del árbol de directorios que se está monitoreando o en el árbol de directorios que se está monitoreando al hacer una estadística() en el archivo. Si stat() falla con un errno de 2, entonces el archivo se ha movido fuera del directorio que se está supervisando, y se puede tratar como si se hubiera eliminado. Si stat() tiene éxito, el evento se puede tratar como si el archivo se hubiera creado.

+0

El enfoque de estadística tiene una condición de carrera: puede haber habido un movimiento encadenado, por ejemplo, por lo que la estadística en una ruta en el medio de la secuencia va a fallar. –

Cuestiones relacionadas