监视特定文件夹的更改并检测Cocoa中更改的文件

时间:2012-11-13 01:52:37

标签: objective-c cocoa filesystems filesystemwatcher

我正在尝试创建一个只监视特定文件夹以进行更改的应用程序,并输出已更改文件的路径。稍后它将对这些已更改的文件进行一些处理。我如何在原生可可中做到这一点?我尝试过以下列出的事情: http://developer.apple.com/library/mac/#featuredarticles/FileSystemEvents/_index.html

但我无法弄清楚如何有效地完成任务。

非常感谢代码示例。

2 个答案:

答案 0 :(得分:3)

fs-notifier

查看Peter Hosey
@interface Notifier : NSObject {
    NSArray *paths; //Actually just one.
    FSEventStreamRef stream;
    struct FSEventStreamContext context;
}

+ (id) notifierWithCallback:(FSEventStreamCallback)newCallback path:(NSString *)newPath;
- (id) initWithCallback:(FSEventStreamCallback)newCallback path:(NSString *)newPath;

- (void) start;
- (void) stop;

@end
#import "Notifier.h"

@implementation Notifier

+ (id) notifierWithCallback:(FSEventStreamCallback)newCallback path:(NSString *)newPath {
    return [[[self alloc] initWithCallback:newCallback path:newPath] autorelease];
}
- (id) initWithCallback:(FSEventStreamCallback)newCallback path:(NSString *)newPath {
    if((self = [super init])) {
        paths = [[NSArray arrayWithObject:newPath] retain];
        context.version = 0L;
        context.info = newPath;
        context.retain = (CFAllocatorRetainCallBack)CFRetain;
        context.release = (CFAllocatorReleaseCallBack)CFRelease;
        context.copyDescription = (CFAllocatorCopyDescriptionCallBack)CFCopyDescription;

        stream = FSEventStreamCreate(kCFAllocatorDefault, newCallback, &context, (CFArrayRef)paths, kFSEventStreamEventIdSinceNow, /*latency*/ 1.0, kFSEventStreamCreateFlagUseCFTypes);
        if (!stream) {
            NSLog(@"Could not create event stream for path %@", newPath);
            [self release];
            return nil;
        }

        FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    }
    return self;
}

- (void) dealloc {
    [self stop];
    FSEventStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    CFRelease(stream);
    [super dealloc];
}

- (void) start {
    FSEventStreamStart(stream);
}
- (void) stop {
    FSEventStreamStop(stream);
}

@end

#import "Notifier.h"

static void gotEvent(ConstFSEventStreamRef streamRef, 
                     void *clientCallBackInfo, 
                     size_t numEvents, 
                     void *eventPaths, 
                     const FSEventStreamEventFlags eventFlags[], 
                     const FSEventStreamEventId eventIds[]);

int main (int argc, char **argv) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    NSArray *paths = [[NSProcessInfo processInfo] arguments];

    NSMutableArray *streams = [NSMutableArray arrayWithCapacity:[paths count]];
    for (NSString *path in paths) {
        [streams addObject:[Notifier notifierWithCallback:gotEvent path:path]];
    }

    [streams makeObjectsPerformSelector:@selector(start)];
    CFRunLoopRun();

    [pool drain];
    return EXIT_SUCCESS;
}

static void gotEvent(ConstFSEventStreamRef stream, 
                     void *clientCallBackInfo, 
                     size_t numEvents, 
                     void *eventPathsVoidPointer, 
                     const FSEventStreamEventFlags eventFlags[], 
                     const FSEventStreamEventId eventIds[]
) {
    NSArray *eventPaths = eventPathsVoidPointer;
    NSString *streamName = clientCallBackInfo;
    NSLog(@"%@: %@", streamName, [eventPaths objectAtIndex:0UL]);
}

答案 1 :(得分:0)

示例是做你想做的事情的基本方法。

查看Using the FSEvents Framework文档。它告诉您启动和运行所需的一切。我在这里给出的代码示例与文档中列出的相同。