DocInteraction 检测本地目录…

 


#import


@class DirectoryWatcher;


@protocol DirectoryWatcherDelegate <<span style="color: #703daa">NSObject>

@required

- (void)directoryDidChange:(DirectoryWatcher *)folderWatcher;

@end


@interface DirectoryWatcher : NSObject 

{

id <</span>DirectoryWatcherDelegate> delegate;

    

int dirFD;

    int kq;


CFFileDescriptorRef dirKQRef;

}

@property (nonatomic, assign) id <</span>DirectoryWatcherDelegate> delegate;


+ (DirectoryWatcher *)watchFolderWithPath:(NSString *)watchPath delegate:(id<<span style="color: #4f8187">DirectoryWatcherDelegate>)watchDelegate;

- (void)invalidate;

@end


---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ----------------

 


#import "DirectoryWatcher.h"


#include

#include

#include

#include

#include


#import


@interface DirectoryWatcher (DirectoryWatcherPrivate)

- (BOOL)startMonitoringDirectory:(NSString *)dirPath;

- (void)kqueueFired;

@end



#pragma mark -


@implementation DirectoryWatcher


@synthesize delegate;


- (id)init

{

self= [super init];

delegate = NULL;


dirFD = -1;

    kq = -1;

dirKQRef = NULL;

 

return self;

}


- (void)dealloc

{

[self invalidate];

[super dealloc];

}


+ (DirectoryWatcher *)watchFolderWithPath:(NSString *)watchPath delegate:(id)watchDelegate

{

DirectoryWatcher *retVal = NULL;

if ((watchDelegate != NULL) && (watchPath != NULL))

{

DirectoryWatcher *tempManager = [[[DirectoryWatcher alloc] init] autorelease];

tempManager.delegate = watchDelegate;

if ([tempManager startMonitoringDirectory: watchPath])

{

// Everything appears to be in order, so return the DirectoryWatcher.  

// Otherwise we'll fall through and return NULL.

retVal = tempManager;

}

}

return retVal;

}


- (void)invalidate

{

if (dirKQRef != NULL)

{

CFFileDescriptorInvalidate(dirKQRef);

CFRelease(dirKQRef);

dirKQRef = NULL;

// We don't need to close the kq, CFFileDescriptorInvalidate closed it instead.

// Change the value so no one thinks it's still live.

kq = -1;

}

 

if(dirFD != -1)

{

close(dirFD);

dirFD = -1;

}

}


@end



#pragma mark -


@implementation DirectoryWatcher (DirectoryWatcherPrivate)


- (void)kqueueFired

{

    assert(kq >= 0);


    struct kevent   event;

    struct timespec timeout = {0, 0};

    int             eventCount;

 

    eventCount = kevent(kq, NULL, 0, &event, 1, &timeout);

    assert((eventCount >= 0) && (eventCount < 2));

    

// call our delegate of the directory change

    [delegate directoryDidChange:self];


    CFFileDescriptorEnableCallBacks(dirKQRef, kCFFileDescriptorReadCallBack);

}


static void KQCallback(CFFileDescriptorRef kqRef, CFOptionFlags callBackTypes, void *info)

{

    DirectoryWatcher *obj;

 

    obj = (DirectoryWatcher *)info;

    assert([obj isKindOfClass:[DirectoryWatcher class]]);

    assert(kqRef == obj->dirKQRef);

    assert(callBackTypes == kCFFileDescriptorReadCallBack);

 

    [obj kqueueFired];

}


- (BOOL)startMonitoringDirectory:(NSString *)dirPath

{

// Double initializing is not going to work...

if ((dirKQRef == NULL) && (dirFD == -1) && (kq == -1))

{

// Open the directory we're going to watch

dirFD = open([dirPath fileSystemRepresentation], O_EVTONLY);

if (dirFD >= 0)

{

// Create a kqueue for our event messages...

kq = kqueue();

if (kq >= 0)

{

struct kevent eventToAdd;

eventToAdd.ident  = dirFD;

eventToAdd.filter = EVFILT_VNODE;

eventToAdd.flags  = EV_ADD | EV_CLEAR;

eventToAdd.fflags = NOTE_WRITE;

eventToAdd.data   = 0;

eventToAdd.udata  = NULL;

 

int errNum = kevent(kq, &eventToAdd, 1, NULL, 0, NULL);

if (errNum == 0)

{

CFFileDescriptorContext context = { 0, self, NULL, NULL, NULL };

CFRunLoopSourceRef      rls;


// Passing true in the third argument so CFFileDescriptorInvalidate will close kq.

dirKQRef = CFFileDescriptorCreate(NULL, kq, true, KQCallback, &context);

if (dirKQRef != NULL)

{

rls = CFFileDescriptorCreateRunLoopSource(NULL, dirKQRef, 0);

if (rls != NULL)

{

CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);

CFRelease(rls);

CFFileDescriptorEnableCallBacks(dirKQRef, kCFFileDescriptorReadCallBack);

 

// If everything worked, return early and bypass shutting things down

return YES;

}

// Couldn't create a runloop source, invalidate and release the CFFileDescriptorRef

CFFileDescriptorInvalidate(dirKQRef);

                        CFRelease(dirKQRef);

dirKQRef = NULL;

}

}

// kq is active, but something failed, close the handle...

close(kq);

kq = -1;

}

// file handle is open, but something failed, close the handle...

close(dirFD);

dirFD = -1;

}

}

return NO;

}

@end


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值