I have a kQueue observer on the Documents directory in my app. I am using the kQueue that triggers a callback when the Documents directory contents changes.
here are two of the settings
eventToAdd.flags = EV_ADD | EV_CLEAR;
eventToAdd.fflags = NOTE_WRITE;
The problem is that I get notified when the contents changed when a new file is added, but the actual file is not completely copied yet, so when I try process the new file I get a SIGABRT crash.
How can I delay the notification until the file is completed?
I solved this by creating 2 listeners... one on the app's Documents directory to watch for new files appearing, and a File proxy object that is created for each file that appears. The File object has a fileBusy
flag. The File object sets a 2 second timer when a chunk of data is written to the file. I assume the file is completely written if no updates before the timer expires.
File change listener code here: https://gist.github.com/nielsbot/5155671
My (partial) delegate for the above listener below. (The "File" object that represents a file on disk)
@implementation File<FileChangeObserverDelegate>
-(void)scheduleFileBusyTimeout
{
self.fileBusyTimeoutTimer = [ NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector( fileBusyTimeoutTimerFired: ) userInfo:nil repeats:NO ] ;
}
-(void)setFileChangeObserver:(FileChangeObserver *)observer
{
[_fileChangeObserver invalidate ] ;
_fileChangeObserver = observer ;
}
-(void)fileChanged:(FileChangeObserver *)asset typeMask:(enum FileChangeNotificationType)type
{
@synchronized( self )
{
if ( ( type & kFileChangeType_Delete ) != 0 )
{
// we're going away soon...
self.fileChangeObserver = nil ;
}
else
{
self.fileBusy = YES ;
[ self scheduleFileBusyTimeout ] ;
}
}
}
-(void)fileBusyTimeoutTimerFired:(NSTimer*)timer
{
@autoreleasepool {
self.fileBusy = NO ;
}
}
-(void)setFileBusyTimeoutTimer:(NSTimer *)timer
{
[ _fileBusyTimeoutTimer invalidate ] ;
_fileBusyTimeoutTimer = timer ;
}
@end