MacOS 开发

来源:互联网 发布:奥登cba数据 编辑:程序博客网 时间:2024/05/29 10:41

  • file system events 的构成
  • 简单使用介绍
  • Demo 地址
  • 使用
    • 1导入 CoreServices 框架
    • 2添加属性
    • 3申明 fsevents_callback 方法
    • 4实现fsevents_callback 方法
    • 5开始监控
    • 6取消监控
    • 7实现私有方法
    • 运行结果
  • 参考资料


file system events 的构成

FSEventStream 是一套 C 语言的方法, 类似于 CoreGraphic.
file system events API提供了 文件目录层次改变 的通知(支持10.5以上),该机制(file system events mechanism)由3部分构成:

1、内核传递事件到用户层;
2、一个后台进程过滤事件流,然后发送通知;
3、一个数据库保存这些改变。

开发者注册通知,后台进程发送出了通知以后,就能接收到,然后做相应的处理。


简单使用介绍:

1:应用程序通过 FSEventStreamCreate or FSEventStreamCreateRelativeToDevice注册、创建一个文件监控句柄。

2:使用循环来获取FSEventStreamScheduleWithRunLoop。

3:告诉后台进程开始文件监控FSEventStreamStart。

4:如果事件产生,然后就回调函数FSEventStreamCallback

5:停止后台进程发送通知FSEventStreamStop.

6:作废事件 FSEventStreamInvalidate.

7:释放事件 FSEventStreamRelease.


Demo 地址

  • FSEventStreamDemo 亲测好用
    https://github.com/ywwzwb/FSEventStreamDemo

使用

1、导入 CoreServices 框架

import <CoreServices/CoreServices.h>

2、添加属性

@property(nonatomic) NSInteger syncEventID;@property(nonatomic, assign) FSEventStreamRef syncEventStream;

并加载

#pragma mark - setter-(void)setSyncEventID:(NSInteger)syncEventID{    [[NSUserDefaults standardUserDefaults] setInteger:syncEventID forKey:@"SyncEventID"];}-(NSInteger)syncEventID {    NSInteger syncEventID = [[NSUserDefaults standardUserDefaults] integerForKey:@"SyncEventID"];    if(syncEventID == 0) {        syncEventID = kFSEventStreamEventIdSinceNow;    }    return syncEventID;}

3、申明 fsevents_callback 方法

void fsevents_callback(ConstFSEventStreamRef streamRef,                       void *userData,                       size_t numEvents,                       void *eventPaths,                       const FSEventStreamEventFlags eventFlags[],                       const FSEventStreamEventId eventIds[]);

4、实现fsevents_callback 方法

void fsevents_callback(ConstFSEventStreamRef streamRef,                       void *userData,                       size_t numEvents,                       void *eventPaths,                       const FSEventStreamEventFlags eventFlags[],                       const FSEventStreamEventId eventIds[]) {    ViewController *self = (__bridge ViewController *)userData;    NSArray *pathArr = (__bridge NSArray*)eventPaths;    FSEventStreamEventId lastRenameEventID = 0;    NSString* lastPath = nil;    for(int i=0; i<numEvents; i++){        FSEventStreamEventFlags flag = eventFlags[i];        if(kFSEventStreamEventFlagItemCreated & flag) {            NSLog(@"create file: %@", pathArr[i]);        }        if(kFSEventStreamEventFlagItemRenamed & flag) {            FSEventStreamEventId currentEventID = eventIds[i];            NSString* currentPath = pathArr[i];            if (currentEventID == lastRenameEventID + 1) {                // 重命名或者是移动文件                NSLog(@"mv %@ %@", lastPath, currentPath);            } else {                // 其他情况, 例如移动进来一个文件, 移动出去一个文件, 移动文件到回收站                if ([[NSFileManager defaultManager] fileExistsAtPath:currentPath]) {                    // 移动进来一个文件                    NSLog(@"move in file: %@", currentPath);                } else {                    // 移出一个文件                    NSLog(@"move out file: %@", currentPath);                }            }            lastRenameEventID = currentEventID;            lastPath = currentPath;        }        if(kFSEventStreamEventFlagItemRemoved & flag) {            NSLog(@"remove: %@", pathArr[i]);        }        if(kFSEventStreamEventFlagItemModified & flag) {            NSLog(@"modify: %@", pathArr[i]);        }    }    [self updateEventID];}

5、开始监控

记得修改你的监控文件夹,你也可以使用代码自动设定文件夹位置

#pragma mark - event- (IBAction)startWatchClicked:(id)sender {    if(self.syncEventStream) {        FSEventStreamStop(self.syncEventStream);        FSEventStreamInvalidate(self.syncEventStream);        FSEventStreamRelease(self.syncEventStream);        self.syncEventStream = NULL;    }    NSArray *paths = @[@"/Users/user/Desktop"];// 这里填入需要监控的文件夹    FSEventStreamContext context;    context.info = (__bridge void * _Nullable)(self);    context.version = 0;    context.retain = NULL;    context.release = NULL;    context.copyDescription = NULL;    self.syncEventStream = FSEventStreamCreate(NULL, &fsevents_callback, &context, (__bridge CFArrayRef _Nonnull)(paths), self.syncEventID, 1, kFSEventStreamCreateFlagFileEvents | kFSEventStreamCreateFlagUseCFTypes);    FSEventStreamScheduleWithRunLoop(self.syncEventStream, CFRunLoopGetMain(), kCFRunLoopDefaultMode);    FSEventStreamStart(self.syncEventStream);}

6、取消监控

- (IBAction)stopWatchClicked:(id)sender {    if(self.syncEventStream) {        FSEventStreamStop(self.syncEventStream);        FSEventStreamInvalidate(self.syncEventStream);        FSEventStreamRelease(self.syncEventStream);        self.syncEventStream = NULL;    }}

7、实现私有方法

#pragma mark - private method-(void)updateEventID {    self.syncEventID = FSEventStreamGetLatestEventId(self.syncEventStream);}

运行结果:

在桌面创建一个文件夹,并把文件夹改名为 123后,打印结果如下:

 22:06:01.976 -  create file: /Users/user/Desktop/未命名文件夹 22:06:01.976 -  modify: /Users/user/Desktop/.DS_Store 22:06:05.203 -  create file: /Users/user/Desktop/未命名文件夹 22:06:05.203 -  move out file: /Users/user/Desktop/未命名文件夹 22:06:05.203 -  mv /Users/user/Desktop/未命名文件夹 /Users/user/Desktop/123 22:06:08.581 -  modify: /Users/user/Desktop/.DS_Store

参考资料

  • yww:使用 FSEventStream 监控 Mac 文件变化
    http://www.jianshu.com/p/7c37b39b143e

  • AlexJing_WU:watch File System Events(文件系统改变事件监控)
    http://blog.csdn.net/u012972257/article/details/17302985