76 lines
2.4 KiB
Objective-C
76 lines
2.4 KiB
Objective-C
#import "DirectoryWatcher.h"
|
|
#import <CoreServices/CoreServices.h>
|
|
|
|
void callback(ConstFSEventStreamRef streamRef, void * info, size_t numEvents, void * eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]);
|
|
|
|
@interface DirectoryWatcher ()
|
|
|
|
@property NSString * path;
|
|
@property NSMutableSet<NSString*>* knownFiles;
|
|
@property FSEventStreamRef stream;
|
|
|
|
- (void)rescanPathWithEvents:(BOOL)sendEvents;
|
|
|
|
@end
|
|
|
|
@implementation DirectoryWatcher
|
|
|
|
- (instancetype)initWithPath:(NSString *)path {
|
|
if (!path) {
|
|
return nil;
|
|
}
|
|
|
|
self = [super init];
|
|
if (self) {
|
|
self.path = path;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc {
|
|
[self stopWatching];
|
|
}
|
|
|
|
- (void)startWatching {
|
|
self.knownFiles = [NSMutableSet new];
|
|
[self rescanPathWithEvents:NO];
|
|
|
|
CFStringRef path = (__bridge CFStringRef)(self.path);
|
|
CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void**)&path, 1, NULL);
|
|
CFAbsoluteTime latency = 1;
|
|
FSEventStreamContext context = { 0, (__bridge void * _Nullable)(self), NULL, NULL, NULL };
|
|
self.stream = FSEventStreamCreate(NULL, &callback, &context, pathsToWatch, kFSEventStreamEventIdSinceNow, latency, kFSEventStreamCreateFlagNone);
|
|
FSEventStreamScheduleWithRunLoop(self.stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
|
FSEventStreamStart(self.stream);
|
|
}
|
|
|
|
- (void)stopWatching {
|
|
if (self.stream) {
|
|
FSEventStreamStop(self.stream);
|
|
FSEventStreamInvalidate(self.stream);
|
|
FSEventStreamRelease(self.stream);
|
|
self.stream = nil;
|
|
}
|
|
}
|
|
|
|
- (void)rescanPathWithEvents:(BOOL)sendEvents {
|
|
NSArray<NSString*>* downloadFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.path error:nil];
|
|
NSMutableSet<NSString*>* fullSet = [NSMutableSet new];
|
|
for (NSString * file in downloadFiles) {
|
|
[fullSet addObject:file];
|
|
if (![self.knownFiles containsObject:file]) {
|
|
if (sendEvents) {
|
|
[self.delegate watcher:self observedNewFileAtPath:file];
|
|
}
|
|
}
|
|
}
|
|
self.knownFiles = fullSet;
|
|
}
|
|
|
|
@end
|
|
|
|
void callback(ConstFSEventStreamRef streamRef, void * info, size_t numEvents, void * eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) {
|
|
DirectoryWatcher * watcher = (__bridge DirectoryWatcher*)info;
|
|
[watcher rescanPathWithEvents:YES];
|
|
}
|