Notification of changes to the iPhone's /Documents directory

社会主义新天地 提交于 2019-11-26 08:07:27

问题


We have an app that uses file sharing. UIFileSharingEnable is set etc. and it all seems to work fine, but I\'m looking for some sort of notification of when files have been added/deleted on the iPhone side. Can anyone advise?

Cheers in advance.


回答1:


This thread on the Apple Developer Forums may be of interest, in which it is suggested that you run a kqueue in its own thread, tracking the app's Documents folder.

An Apple tech followed up with some 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);
}



回答2:


Here's an alternative solution using Grand Central Dispatch (GCD) that allows you to receive file change notifications from NSNotificationCenter:

Add these variables to the class's interface:

// Dispatch queue
dispatch_queue_t _dispatchQueue;

// A source of potential notifications
dispatch_source_t _source;

Add the following code to the implementation:

    #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!");
    }];



回答3:


Old question, but I came across this Apple code that includes a directory monitor. Note that it triggers the moment a file is added (or removed); this could be before the OS has completed writing to the file.



来源:https://stackoverflow.com/questions/3181821/notification-of-changes-to-the-iphones-documents-directory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!