更改iPhone/Documents目录的通知

问题描述:

我们有一个使用文件共享的应用程序。 UIFileSharingEnable设置等,它似乎工作正常,但我正在寻找某种类型的文件已被添加/删除iPhone端的通知。任何人都可以建议吗?更改iPhone/Documents目录的通知

提前欢呼。

This thread在Apple开发者论坛上可能会感兴趣,其中建议您在其自己的线程中运行kqueue,跟踪应用程序的Documents文件夹。

苹果公司的技术跟进一些sample code here

- (void)kqueueFired 
{ 
    int    kq; 
    struct kevent event; 
    struct timespec timeout = { 0, 0 }; 
    int    eventCount; 

    kq = CFFileDescriptorGetNativeDescriptor(self->_kqRef); 
    assert(kq >= 0); 

    eventCount = kevent(kq, NULL, 0, &event, 1, &timeout); 
    assert((eventCount >= 0) && (eventCount < 2)); 

    if (eventCount == 1) { 
     NSLog(@"dir changed"); 
    }  

    CFFileDescriptorEnableCallBacks(self->_kqRef, kCFFileDescriptorReadCallBack); 
} 

static void KQCallback(CFFileDescriptorRef kqRef, CFOptionFlags callBackTypes, void *info) 
{ 
    ViewController * obj; 

    obj = (ViewController *) info; 
    assert([obj isKindOfClass:[ViewController class]]); 
    assert(kqRef == obj->_kqRef); 
    assert(callBackTypes == kCFFileDescriptorReadCallBack); 

    [obj kqueueFired]; 
} 

- (IBAction)testAction:(id)sender 
{ 
    #pragma unused(sender) 
    NSString *    docPath; 
    int      dirFD; 
    int      kq; 
    int      retVal; 
    struct kevent   eventToAdd; 
    CFFileDescriptorContext context = { 0, self, NULL, NULL, NULL }; 
    CFRunLoopSourceRef  rls; 

    docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
    assert(docPath != 0); 

    NSLog(@"%@", docPath); 

    dirFD = open([docPath fileSystemRepresentation], O_EVTONLY); 
    assert(dirFD >= 0); 

    kq = kqueue(); 
    assert(kq >= 0); 

    eventToAdd.ident = dirFD; 
    eventToAdd.filter = EVFILT_VNODE; 
    eventToAdd.flags = EV_ADD | EV_CLEAR; 
    eventToAdd.fflags = NOTE_WRITE; 
    eventToAdd.data = 0; 
    eventToAdd.udata = NULL; 

    retVal = kevent(kq, &eventToAdd, 1, NULL, 0, NULL); 
    assert(retVal == 0); 

    assert(self->_kqRef == NULL); 

    self->_kqRef = CFFileDescriptorCreate(NULL, kq, true, KQCallback, &context); 
    assert(self->_kqRef != NULL); 

    rls = CFFileDescriptorCreateRunLoopSource(NULL, self->_kqRef, 0); 
    assert(rls != NULL); 

    CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 

    CFRelease(rls); 

    CFFileDescriptorEnableCallBacks(self->_kqRef, kCFFileDescriptorReadCallBack); 
} 
+0

作品一种享受! 谢谢亚历克斯。 – 2010-07-07 14:53:10

+4

你需要包括这些标题: '#包括 的#include 的#include 的#include 的#include ' – Dustin 2011-05-06 15:14:45

+1

什么,如果我想在监测和发现文档文件夹中调用某个函数的文件,还有我把这三个功能放在appdelegate类或什么 – AMH 2011-07-18 07:13:26

老问题,但我碰到this Apple code包括目录监视器来了。请注意,它会触发文件添加(或删除)的时刻;这可能在操作系统完成写入文件之前。

+0

+1这对我有帮助! – ZYiOS 2012-11-17 14:27:22

+1

如何等待文件完全写入,因为它早早启动,当我访问它时,我得到一个SIGABRT。 – jarryd 2013-03-04 15:13:53

下面是使用大中央调度(GCD),它允许你从NSNotificationCenter收到文件更改通知的替代解决方案:

这些变量添加到类的接口:

// Dispatch queue 
dispatch_queue_t _dispatchQueue; 

// A source of potential notifications 
dispatch_source_t _source; 

下面的代码添加到执行:

#define fileChangedNotification @"fileChangedNotification" 

    // Get the path to the home directory 
    NSString * homeDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; 

    // Create a new file descriptor - we need to convert the NSString to a char * i.e. C style string 
    int filedes = open([homeDirectory cStringUsingEncoding:NSASCIIStringEncoding], O_EVTONLY); 

    // Create a dispatch queue - when a file changes the event will be sent to this queue 
    _dispatchQueue = dispatch_queue_create("FileMonitorQueue", 0); 

    // Create a GCD source. This will monitor the file descriptor to see if a write command is detected 
    // The following options are available 

    /*! 
    * @typedef dispatch_source_vnode_flags_t 
    * Type of dispatch_source_vnode flags 
    * 
    * @constant DISPATCH_VNODE_DELETE 
    * The filesystem object was deleted from the namespace. 
    * 
    * @constant DISPATCH_VNODE_WRITE 
    * The filesystem object data changed. 
    * 
    * @constant DISPATCH_VNODE_EXTEND 
    * The filesystem object changed in size. 
    * 
    * @constant DISPATCH_VNODE_ATTRIB 
    * The filesystem object metadata changed. 
    * 
    * @constant DISPATCH_VNODE_LINK 
    * The filesystem object link count changed. 
    * 
    * @constant DISPATCH_VNODE_RENAME 
    * The filesystem object was renamed in the namespace. 
    * 
    * @constant DISPATCH_VNODE_REVOKE 
    * The filesystem object was revoked. 
    */ 

    // Write covers - adding a file, renaming a file and deleting a file... 
    _source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE,filedes, 
                 DISPATCH_VNODE_WRITE, 
                 _dispatchQueue); 


    // This block will be called when teh file changes 
    dispatch_source_set_event_handler(_source, ^(){ 
     // We call an NSNotification so the file can change can be detected anywhere 
     [[NSNotificationCenter defaultCenter] postNotificationName:fileChangedNotification object:Nil]; 
    }); 

    // When we stop monitoring the file this will be called and it will close the file descriptor 
    dispatch_source_set_cancel_handler(_source, ^() { 
     close(filedes); 
    }); 

    // Start monitoring the file... 
    dispatch_resume(_source); 

    //... 

    // When we want to stop monitoring the file we call this 
    //dispatch_source_cancel(source); 


    // To recieve a notification about the file change we can use the NSNotificationCenter 
    [[NSNotificationCenter defaultCenter] addObserverForName:fileChangedNotification object:Nil queue:Nil usingBlock:^(NSNotification * notification) { 
     NSLog(@"File change detected!"); 
    }]; 
+0

非常感谢!简单和完美的作品。 – Ravi 2014-06-26 15:08:39